xref: /aosp_15_r20/external/libcups/scheduler/subscriptions.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Subscription routines for the CUPS scheduler.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.	See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  */
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #include "cupsd.h"
16*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DBUS
17*5e7646d2SAndroid Build Coastguard Worker #  include <dbus/dbus.h>
18*5e7646d2SAndroid Build Coastguard Worker #  ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND
19*5e7646d2SAndroid Build Coastguard Worker #    define dbus_message_append_iter_init dbus_message_iter_init_append
20*5e7646d2SAndroid Build Coastguard Worker #    define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &(v))
21*5e7646d2SAndroid Build Coastguard Worker #    define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &(v))
22*5e7646d2SAndroid Build Coastguard Worker #  endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
23*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DBUS */
24*5e7646d2SAndroid Build Coastguard Worker 
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker /*
27*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
28*5e7646d2SAndroid Build Coastguard Worker  */
29*5e7646d2SAndroid Build Coastguard Worker 
30*5e7646d2SAndroid Build Coastguard Worker static int	cupsd_compare_subscriptions(cupsd_subscription_t *first,
31*5e7646d2SAndroid Build Coastguard Worker 					    cupsd_subscription_t *second,
32*5e7646d2SAndroid Build Coastguard Worker 					    void *unused);
33*5e7646d2SAndroid Build Coastguard Worker static void	cupsd_delete_event(cupsd_event_t *event);
34*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DBUS
35*5e7646d2SAndroid Build Coastguard Worker static void	cupsd_send_dbus(cupsd_eventmask_t event, cupsd_printer_t *dest,
36*5e7646d2SAndroid Build Coastguard Worker 				cupsd_job_t *job);
37*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DBUS */
38*5e7646d2SAndroid Build Coastguard Worker static void	cupsd_send_notification(cupsd_subscription_t *sub,
39*5e7646d2SAndroid Build Coastguard Worker 					cupsd_event_t *event);
40*5e7646d2SAndroid Build Coastguard Worker static void	cupsd_start_notifier(cupsd_subscription_t *sub);
41*5e7646d2SAndroid Build Coastguard Worker static void	cupsd_update_notifier(void);
42*5e7646d2SAndroid Build Coastguard Worker 
43*5e7646d2SAndroid Build Coastguard Worker 
44*5e7646d2SAndroid Build Coastguard Worker /*
45*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdAddEvent()' - Add an event to the global event cache.
46*5e7646d2SAndroid Build Coastguard Worker  */
47*5e7646d2SAndroid Build Coastguard Worker 
48*5e7646d2SAndroid Build Coastguard Worker void
cupsdAddEvent(cupsd_eventmask_t event,cupsd_printer_t * dest,cupsd_job_t * job,const char * text,...)49*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(
50*5e7646d2SAndroid Build Coastguard Worker     cupsd_eventmask_t event,		/* I - Event */
51*5e7646d2SAndroid Build Coastguard Worker     cupsd_printer_t   *dest,		/* I - Printer associated with event */
52*5e7646d2SAndroid Build Coastguard Worker     cupsd_job_t	      *job,		/* I - Job associated with event */
53*5e7646d2SAndroid Build Coastguard Worker     const char	      *text,		/* I - Notification text */
54*5e7646d2SAndroid Build Coastguard Worker     ...)				/* I - Additional arguments as needed */
55*5e7646d2SAndroid Build Coastguard Worker {
56*5e7646d2SAndroid Build Coastguard Worker   va_list		ap;		/* Pointer to additional arguments */
57*5e7646d2SAndroid Build Coastguard Worker   char			ftext[1024];	/* Formatted text buffer */
58*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Printer/job attribute */
59*5e7646d2SAndroid Build Coastguard Worker   cupsd_event_t		*temp;		/* New event pointer */
60*5e7646d2SAndroid Build Coastguard Worker   cupsd_subscription_t	*sub;		/* Current subscription */
61*5e7646d2SAndroid Build Coastguard Worker 
62*5e7646d2SAndroid Build Coastguard Worker 
63*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG2,
64*5e7646d2SAndroid Build Coastguard Worker 		  "cupsdAddEvent(event=%s, dest=%p(%s), job=%p(%d), text=\"%s\", ...)",
65*5e7646d2SAndroid Build Coastguard Worker 		  cupsdEventName(event), dest, dest ? dest->name : "",
66*5e7646d2SAndroid Build Coastguard Worker 		  job, job ? job->id : 0, text);
67*5e7646d2SAndroid Build Coastguard Worker 
68*5e7646d2SAndroid Build Coastguard Worker  /*
69*5e7646d2SAndroid Build Coastguard Worker   * Keep track of events with any OS-supplied notification mechanisms...
70*5e7646d2SAndroid Build Coastguard Worker   */
71*5e7646d2SAndroid Build Coastguard Worker 
72*5e7646d2SAndroid Build Coastguard Worker   LastEvent |= event;
73*5e7646d2SAndroid Build Coastguard Worker 
74*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DBUS
75*5e7646d2SAndroid Build Coastguard Worker   cupsd_send_dbus(event, dest, job);
76*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DBUS */
77*5e7646d2SAndroid Build Coastguard Worker 
78*5e7646d2SAndroid Build Coastguard Worker  /*
79*5e7646d2SAndroid Build Coastguard Worker   * Return if we aren't keeping events...
80*5e7646d2SAndroid Build Coastguard Worker   */
81*5e7646d2SAndroid Build Coastguard Worker 
82*5e7646d2SAndroid Build Coastguard Worker   if (MaxEvents <= 0)
83*5e7646d2SAndroid Build Coastguard Worker   {
84*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_WARN,
85*5e7646d2SAndroid Build Coastguard Worker 		    "cupsdAddEvent: Discarding %s event since MaxEvents is %d!",
86*5e7646d2SAndroid Build Coastguard Worker 		    cupsdEventName(event), MaxEvents);
87*5e7646d2SAndroid Build Coastguard Worker     return;
88*5e7646d2SAndroid Build Coastguard Worker   }
89*5e7646d2SAndroid Build Coastguard Worker 
90*5e7646d2SAndroid Build Coastguard Worker  /*
91*5e7646d2SAndroid Build Coastguard Worker   * Then loop through the subscriptions and add the event to the corresponding
92*5e7646d2SAndroid Build Coastguard Worker   * caches...
93*5e7646d2SAndroid Build Coastguard Worker   */
94*5e7646d2SAndroid Build Coastguard Worker 
95*5e7646d2SAndroid Build Coastguard Worker   for (temp = NULL, sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
96*5e7646d2SAndroid Build Coastguard Worker        sub;
97*5e7646d2SAndroid Build Coastguard Worker        sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
98*5e7646d2SAndroid Build Coastguard Worker   {
99*5e7646d2SAndroid Build Coastguard Worker    /*
100*5e7646d2SAndroid Build Coastguard Worker     * Check if this subscription requires this event...
101*5e7646d2SAndroid Build Coastguard Worker     */
102*5e7646d2SAndroid Build Coastguard Worker 
103*5e7646d2SAndroid Build Coastguard Worker     if ((sub->mask & event) != 0 && (sub->dest == dest || !sub->dest || sub->job == job))
104*5e7646d2SAndroid Build Coastguard Worker     {
105*5e7646d2SAndroid Build Coastguard Worker      /*
106*5e7646d2SAndroid Build Coastguard Worker       * Need this event, so create a new event record...
107*5e7646d2SAndroid Build Coastguard Worker       */
108*5e7646d2SAndroid Build Coastguard Worker 
109*5e7646d2SAndroid Build Coastguard Worker       if ((temp = (cupsd_event_t *)calloc(1, sizeof(cupsd_event_t))) == NULL)
110*5e7646d2SAndroid Build Coastguard Worker       {
111*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_CRIT,
112*5e7646d2SAndroid Build Coastguard Worker 			"Unable to allocate memory for event - %s",
113*5e7646d2SAndroid Build Coastguard Worker 			strerror(errno));
114*5e7646d2SAndroid Build Coastguard Worker 	return;
115*5e7646d2SAndroid Build Coastguard Worker       }
116*5e7646d2SAndroid Build Coastguard Worker 
117*5e7646d2SAndroid Build Coastguard Worker       temp->event = event;
118*5e7646d2SAndroid Build Coastguard Worker       temp->time  = time(NULL);
119*5e7646d2SAndroid Build Coastguard Worker       temp->attrs = ippNew();
120*5e7646d2SAndroid Build Coastguard Worker       temp->job	  = job;
121*5e7646d2SAndroid Build Coastguard Worker 
122*5e7646d2SAndroid Build Coastguard Worker       if (dest)
123*5e7646d2SAndroid Build Coastguard Worker 	temp->dest = dest;
124*5e7646d2SAndroid Build Coastguard Worker       else if (job)
125*5e7646d2SAndroid Build Coastguard Worker 	temp->dest = dest = cupsdFindPrinter(job->dest);
126*5e7646d2SAndroid Build Coastguard Worker 
127*5e7646d2SAndroid Build Coastguard Worker      /*
128*5e7646d2SAndroid Build Coastguard Worker       * Add common event notification attributes...
129*5e7646d2SAndroid Build Coastguard Worker       */
130*5e7646d2SAndroid Build Coastguard Worker 
131*5e7646d2SAndroid Build Coastguard Worker       ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_CHARSET,
132*5e7646d2SAndroid Build Coastguard Worker 		   "notify-charset", NULL, "utf-8");
133*5e7646d2SAndroid Build Coastguard Worker 
134*5e7646d2SAndroid Build Coastguard Worker       ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_LANGUAGE,
135*5e7646d2SAndroid Build Coastguard Worker 		   "notify-natural-language", NULL, "en-US");
136*5e7646d2SAndroid Build Coastguard Worker 
137*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
138*5e7646d2SAndroid Build Coastguard Worker 		    "notify-subscription-id", sub->id);
139*5e7646d2SAndroid Build Coastguard Worker 
140*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
141*5e7646d2SAndroid Build Coastguard Worker 		    "notify-sequence-number", sub->next_event_id);
142*5e7646d2SAndroid Build Coastguard Worker 
143*5e7646d2SAndroid Build Coastguard Worker       ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD,
144*5e7646d2SAndroid Build Coastguard Worker 		   "notify-subscribed-event", NULL, cupsdEventName(event));
145*5e7646d2SAndroid Build Coastguard Worker 
146*5e7646d2SAndroid Build Coastguard Worker       if (sub->user_data_len > 0)
147*5e7646d2SAndroid Build Coastguard Worker 	ippAddOctetString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
148*5e7646d2SAndroid Build Coastguard Worker 			  "notify-user-data", sub->user_data,
149*5e7646d2SAndroid Build Coastguard Worker 			  sub->user_data_len);
150*5e7646d2SAndroid Build Coastguard Worker 
151*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
152*5e7646d2SAndroid Build Coastguard Worker 		    "printer-up-time", time(NULL));
153*5e7646d2SAndroid Build Coastguard Worker 
154*5e7646d2SAndroid Build Coastguard Worker       va_start(ap, text);
155*5e7646d2SAndroid Build Coastguard Worker       vsnprintf(ftext, sizeof(ftext), text, ap);
156*5e7646d2SAndroid Build Coastguard Worker       va_end(ap);
157*5e7646d2SAndroid Build Coastguard Worker 
158*5e7646d2SAndroid Build Coastguard Worker       ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_TEXT,
159*5e7646d2SAndroid Build Coastguard Worker 		   "notify-text", NULL, ftext);
160*5e7646d2SAndroid Build Coastguard Worker 
161*5e7646d2SAndroid Build Coastguard Worker       if (dest)
162*5e7646d2SAndroid Build Coastguard Worker       {
163*5e7646d2SAndroid Build Coastguard Worker        /*
164*5e7646d2SAndroid Build Coastguard Worker 	* Add printer attributes...
165*5e7646d2SAndroid Build Coastguard Worker 	*/
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker 	ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_URI, "notify-printer-uri", NULL, dest->uri);
168*5e7646d2SAndroid Build Coastguard Worker 
169*5e7646d2SAndroid Build Coastguard Worker 	ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_NAME, "printer-name", NULL, dest->name);
170*5e7646d2SAndroid Build Coastguard Worker 
171*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_ENUM, "printer-state", (int)dest->state);
172*5e7646d2SAndroid Build Coastguard Worker 
173*5e7646d2SAndroid Build Coastguard Worker 	if (dest->num_reasons == 0)
174*5e7646d2SAndroid Build Coastguard Worker 	  ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "printer-state-reasons", NULL, dest->state == IPP_PRINTER_STOPPED ? "paused" : "none");
175*5e7646d2SAndroid Build Coastguard Worker 	else
176*5e7646d2SAndroid Build Coastguard Worker 	  ippAddStrings(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "printer-state-reasons", dest->num_reasons, NULL, (const char * const *)dest->reasons);
177*5e7646d2SAndroid Build Coastguard Worker 
178*5e7646d2SAndroid Build Coastguard Worker 	ippAddBoolean(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, "printer-is-accepting-jobs", (char)dest->accepting);
179*5e7646d2SAndroid Build Coastguard Worker       }
180*5e7646d2SAndroid Build Coastguard Worker 
181*5e7646d2SAndroid Build Coastguard Worker       if (job)
182*5e7646d2SAndroid Build Coastguard Worker       {
183*5e7646d2SAndroid Build Coastguard Worker        /*
184*5e7646d2SAndroid Build Coastguard Worker 	* Add job attributes...
185*5e7646d2SAndroid Build Coastguard Worker 	*/
186*5e7646d2SAndroid Build Coastguard Worker 
187*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "notify-job-id", job->id);
188*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_ENUM, "job-state", (int)job->state_value);
189*5e7646d2SAndroid Build Coastguard Worker 
190*5e7646d2SAndroid Build Coastguard Worker 	if ((attr = ippFindAttribute(job->attrs, "job-name", IPP_TAG_NAME)) != NULL)
191*5e7646d2SAndroid Build Coastguard Worker 	  ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_NAME, "job-name", NULL, attr->values[0].string.text);
192*5e7646d2SAndroid Build Coastguard Worker 
193*5e7646d2SAndroid Build Coastguard Worker 	switch (job->state_value)
194*5e7646d2SAndroid Build Coastguard Worker 	{
195*5e7646d2SAndroid Build Coastguard Worker 	  case IPP_JOB_PENDING :
196*5e7646d2SAndroid Build Coastguard Worker 	      if (dest && dest->state == IPP_PRINTER_STOPPED)
197*5e7646d2SAndroid Build Coastguard Worker 		ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "printer-stopped");
198*5e7646d2SAndroid Build Coastguard Worker 	      else
199*5e7646d2SAndroid Build Coastguard Worker 		ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "none");
200*5e7646d2SAndroid Build Coastguard Worker 	      break;
201*5e7646d2SAndroid Build Coastguard Worker 
202*5e7646d2SAndroid Build Coastguard Worker 	  case IPP_JOB_HELD :
203*5e7646d2SAndroid Build Coastguard Worker 	      if (ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD) != NULL ||
204*5e7646d2SAndroid Build Coastguard Worker 		  ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME) != NULL)
205*5e7646d2SAndroid Build Coastguard Worker 		ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-hold-until-specified");
206*5e7646d2SAndroid Build Coastguard Worker 	      else
207*5e7646d2SAndroid Build Coastguard Worker 		ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-incoming");
208*5e7646d2SAndroid Build Coastguard Worker 	      break;
209*5e7646d2SAndroid Build Coastguard Worker 
210*5e7646d2SAndroid Build Coastguard Worker 	  case IPP_JOB_PROCESSING :
211*5e7646d2SAndroid Build Coastguard Worker 	      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-printing");
212*5e7646d2SAndroid Build Coastguard Worker 	      break;
213*5e7646d2SAndroid Build Coastguard Worker 
214*5e7646d2SAndroid Build Coastguard Worker 	  case IPP_JOB_STOPPED :
215*5e7646d2SAndroid Build Coastguard Worker 	      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-stopped");
216*5e7646d2SAndroid Build Coastguard Worker 	      break;
217*5e7646d2SAndroid Build Coastguard Worker 
218*5e7646d2SAndroid Build Coastguard Worker 	  case IPP_JOB_CANCELED :
219*5e7646d2SAndroid Build Coastguard Worker 	      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-canceled-by-user");
220*5e7646d2SAndroid Build Coastguard Worker 	      break;
221*5e7646d2SAndroid Build Coastguard Worker 
222*5e7646d2SAndroid Build Coastguard Worker 	  case IPP_JOB_ABORTED :
223*5e7646d2SAndroid Build Coastguard Worker 	      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "aborted-by-system");
224*5e7646d2SAndroid Build Coastguard Worker 	      break;
225*5e7646d2SAndroid Build Coastguard Worker 
226*5e7646d2SAndroid Build Coastguard Worker 	  case IPP_JOB_COMPLETED :
227*5e7646d2SAndroid Build Coastguard Worker 	      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-completed-successfully");
228*5e7646d2SAndroid Build Coastguard Worker 	      break;
229*5e7646d2SAndroid Build Coastguard Worker 	}
230*5e7646d2SAndroid Build Coastguard Worker 
231*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "job-impressions-completed", job->sheets ? job->sheets->values[0].integer : 0);
232*5e7646d2SAndroid Build Coastguard Worker       }
233*5e7646d2SAndroid Build Coastguard Worker 
234*5e7646d2SAndroid Build Coastguard Worker      /*
235*5e7646d2SAndroid Build Coastguard Worker       * Send the notification for this subscription...
236*5e7646d2SAndroid Build Coastguard Worker       */
237*5e7646d2SAndroid Build Coastguard Worker 
238*5e7646d2SAndroid Build Coastguard Worker       cupsd_send_notification(sub, temp);
239*5e7646d2SAndroid Build Coastguard Worker     }
240*5e7646d2SAndroid Build Coastguard Worker   }
241*5e7646d2SAndroid Build Coastguard Worker 
242*5e7646d2SAndroid Build Coastguard Worker   if (temp)
243*5e7646d2SAndroid Build Coastguard Worker     cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
244*5e7646d2SAndroid Build Coastguard Worker   else
245*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_DEBUG, "Discarding unused %s event...", cupsdEventName(event));
246*5e7646d2SAndroid Build Coastguard Worker }
247*5e7646d2SAndroid Build Coastguard Worker 
248*5e7646d2SAndroid Build Coastguard Worker 
249*5e7646d2SAndroid Build Coastguard Worker /*
250*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdAddSubscription()' - Add a new subscription object.
251*5e7646d2SAndroid Build Coastguard Worker  */
252*5e7646d2SAndroid Build Coastguard Worker 
253*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *			/* O - New subscription object */
cupsdAddSubscription(unsigned mask,cupsd_printer_t * dest,cupsd_job_t * job,const char * uri,int sub_id)254*5e7646d2SAndroid Build Coastguard Worker cupsdAddSubscription(
255*5e7646d2SAndroid Build Coastguard Worker     unsigned	    mask,		/* I - Event mask */
256*5e7646d2SAndroid Build Coastguard Worker     cupsd_printer_t *dest,		/* I - Printer, if any */
257*5e7646d2SAndroid Build Coastguard Worker     cupsd_job_t	    *job,		/* I - Job, if any */
258*5e7646d2SAndroid Build Coastguard Worker     const char	    *uri,		/* I - notify-recipient-uri, if any */
259*5e7646d2SAndroid Build Coastguard Worker     int		    sub_id)		/* I - notify-subscription-id or 0 */
260*5e7646d2SAndroid Build Coastguard Worker {
261*5e7646d2SAndroid Build Coastguard Worker   cupsd_subscription_t	*temp;		/* New subscription object */
262*5e7646d2SAndroid Build Coastguard Worker 
263*5e7646d2SAndroid Build Coastguard Worker 
264*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG,
265*5e7646d2SAndroid Build Coastguard Worker 		  "cupsdAddSubscription(mask=%x, dest=%p(%s), job=%p(%d), "
266*5e7646d2SAndroid Build Coastguard Worker 		  "uri=\"%s\")",
267*5e7646d2SAndroid Build Coastguard Worker 		  mask, dest, dest ? dest->name : "", job, job ? job->id : 0,
268*5e7646d2SAndroid Build Coastguard Worker 		  uri ? uri : "(null)");
269*5e7646d2SAndroid Build Coastguard Worker 
270*5e7646d2SAndroid Build Coastguard Worker   if (!Subscriptions)
271*5e7646d2SAndroid Build Coastguard Worker     Subscriptions = cupsArrayNew((cups_array_func_t)cupsd_compare_subscriptions,
272*5e7646d2SAndroid Build Coastguard Worker 				 NULL);
273*5e7646d2SAndroid Build Coastguard Worker 
274*5e7646d2SAndroid Build Coastguard Worker   if (!Subscriptions)
275*5e7646d2SAndroid Build Coastguard Worker   {
276*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_CRIT,
277*5e7646d2SAndroid Build Coastguard Worker 		    "Unable to allocate memory for subscriptions - %s",
278*5e7646d2SAndroid Build Coastguard Worker 		    strerror(errno));
279*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
280*5e7646d2SAndroid Build Coastguard Worker   }
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker  /*
283*5e7646d2SAndroid Build Coastguard Worker   * Limit the number of subscriptions...
284*5e7646d2SAndroid Build Coastguard Worker   */
285*5e7646d2SAndroid Build Coastguard Worker 
286*5e7646d2SAndroid Build Coastguard Worker   if (MaxSubscriptions > 0 && cupsArrayCount(Subscriptions) >= MaxSubscriptions)
287*5e7646d2SAndroid Build Coastguard Worker   {
288*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_DEBUG,
289*5e7646d2SAndroid Build Coastguard Worker 		    "cupsdAddSubscription: Reached MaxSubscriptions %d "
290*5e7646d2SAndroid Build Coastguard Worker 		    "(count=%d)", MaxSubscriptions,
291*5e7646d2SAndroid Build Coastguard Worker 		    cupsArrayCount(Subscriptions));
292*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
293*5e7646d2SAndroid Build Coastguard Worker   }
294*5e7646d2SAndroid Build Coastguard Worker 
295*5e7646d2SAndroid Build Coastguard Worker   if (MaxSubscriptionsPerJob > 0 && job)
296*5e7646d2SAndroid Build Coastguard Worker   {
297*5e7646d2SAndroid Build Coastguard Worker     int count;				/* Number of job subscriptions */
298*5e7646d2SAndroid Build Coastguard Worker 
299*5e7646d2SAndroid Build Coastguard Worker     for (temp = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions),
300*5e7646d2SAndroid Build Coastguard Worker 	     count = 0;
301*5e7646d2SAndroid Build Coastguard Worker 	 temp;
302*5e7646d2SAndroid Build Coastguard Worker 	 temp = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
303*5e7646d2SAndroid Build Coastguard Worker       if (temp->job == job)
304*5e7646d2SAndroid Build Coastguard Worker 	count ++;
305*5e7646d2SAndroid Build Coastguard Worker 
306*5e7646d2SAndroid Build Coastguard Worker     if (count >= MaxSubscriptionsPerJob)
307*5e7646d2SAndroid Build Coastguard Worker     {
308*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_DEBUG,
309*5e7646d2SAndroid Build Coastguard Worker 		      "cupsdAddSubscription: Reached MaxSubscriptionsPerJob %d "
310*5e7646d2SAndroid Build Coastguard Worker 		      "for job #%d (count=%d)", MaxSubscriptionsPerJob,
311*5e7646d2SAndroid Build Coastguard Worker 		      job->id, count);
312*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
313*5e7646d2SAndroid Build Coastguard Worker     }
314*5e7646d2SAndroid Build Coastguard Worker   }
315*5e7646d2SAndroid Build Coastguard Worker 
316*5e7646d2SAndroid Build Coastguard Worker   if (MaxSubscriptionsPerPrinter > 0 && dest)
317*5e7646d2SAndroid Build Coastguard Worker   {
318*5e7646d2SAndroid Build Coastguard Worker     int count;				/* Number of printer subscriptions */
319*5e7646d2SAndroid Build Coastguard Worker 
320*5e7646d2SAndroid Build Coastguard Worker     for (temp = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions),
321*5e7646d2SAndroid Build Coastguard Worker 	     count = 0;
322*5e7646d2SAndroid Build Coastguard Worker 	 temp;
323*5e7646d2SAndroid Build Coastguard Worker 	 temp = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
324*5e7646d2SAndroid Build Coastguard Worker       if (temp->dest == dest)
325*5e7646d2SAndroid Build Coastguard Worker 	count ++;
326*5e7646d2SAndroid Build Coastguard Worker 
327*5e7646d2SAndroid Build Coastguard Worker     if (count >= MaxSubscriptionsPerPrinter)
328*5e7646d2SAndroid Build Coastguard Worker     {
329*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_DEBUG,
330*5e7646d2SAndroid Build Coastguard Worker 		      "cupsdAddSubscription: Reached "
331*5e7646d2SAndroid Build Coastguard Worker 		      "MaxSubscriptionsPerPrinter %d for %s (count=%d)",
332*5e7646d2SAndroid Build Coastguard Worker 		      MaxSubscriptionsPerPrinter, dest->name, count);
333*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
334*5e7646d2SAndroid Build Coastguard Worker     }
335*5e7646d2SAndroid Build Coastguard Worker   }
336*5e7646d2SAndroid Build Coastguard Worker 
337*5e7646d2SAndroid Build Coastguard Worker  /*
338*5e7646d2SAndroid Build Coastguard Worker   * Allocate memory for this subscription...
339*5e7646d2SAndroid Build Coastguard Worker   */
340*5e7646d2SAndroid Build Coastguard Worker 
341*5e7646d2SAndroid Build Coastguard Worker   if ((temp = calloc(1, sizeof(cupsd_subscription_t))) == NULL)
342*5e7646d2SAndroid Build Coastguard Worker   {
343*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_CRIT,
344*5e7646d2SAndroid Build Coastguard Worker 		    "Unable to allocate memory for subscription object - %s",
345*5e7646d2SAndroid Build Coastguard Worker 		    strerror(errno));
346*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
347*5e7646d2SAndroid Build Coastguard Worker   }
348*5e7646d2SAndroid Build Coastguard Worker 
349*5e7646d2SAndroid Build Coastguard Worker  /*
350*5e7646d2SAndroid Build Coastguard Worker   * Fill in common data...
351*5e7646d2SAndroid Build Coastguard Worker   */
352*5e7646d2SAndroid Build Coastguard Worker 
353*5e7646d2SAndroid Build Coastguard Worker   if (sub_id)
354*5e7646d2SAndroid Build Coastguard Worker   {
355*5e7646d2SAndroid Build Coastguard Worker     temp->id = sub_id;
356*5e7646d2SAndroid Build Coastguard Worker 
357*5e7646d2SAndroid Build Coastguard Worker     if (sub_id >= NextSubscriptionId)
358*5e7646d2SAndroid Build Coastguard Worker       NextSubscriptionId = sub_id + 1;
359*5e7646d2SAndroid Build Coastguard Worker   }
360*5e7646d2SAndroid Build Coastguard Worker   else
361*5e7646d2SAndroid Build Coastguard Worker   {
362*5e7646d2SAndroid Build Coastguard Worker     temp->id = NextSubscriptionId;
363*5e7646d2SAndroid Build Coastguard Worker 
364*5e7646d2SAndroid Build Coastguard Worker     NextSubscriptionId ++;
365*5e7646d2SAndroid Build Coastguard Worker   }
366*5e7646d2SAndroid Build Coastguard Worker 
367*5e7646d2SAndroid Build Coastguard Worker   temp->mask	       = mask;
368*5e7646d2SAndroid Build Coastguard Worker   temp->dest	       = dest;
369*5e7646d2SAndroid Build Coastguard Worker   temp->job	       = job;
370*5e7646d2SAndroid Build Coastguard Worker   temp->pipe	       = -1;
371*5e7646d2SAndroid Build Coastguard Worker   temp->first_event_id = 1;
372*5e7646d2SAndroid Build Coastguard Worker   temp->next_event_id  = 1;
373*5e7646d2SAndroid Build Coastguard Worker 
374*5e7646d2SAndroid Build Coastguard Worker   cupsdSetString(&(temp->recipient), uri);
375*5e7646d2SAndroid Build Coastguard Worker 
376*5e7646d2SAndroid Build Coastguard Worker  /*
377*5e7646d2SAndroid Build Coastguard Worker   * Add the subscription to the array...
378*5e7646d2SAndroid Build Coastguard Worker   */
379*5e7646d2SAndroid Build Coastguard Worker 
380*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(Subscriptions, temp);
381*5e7646d2SAndroid Build Coastguard Worker 
382*5e7646d2SAndroid Build Coastguard Worker  /*
383*5e7646d2SAndroid Build Coastguard Worker   * For RSS subscriptions, run the notifier immediately...
384*5e7646d2SAndroid Build Coastguard Worker   */
385*5e7646d2SAndroid Build Coastguard Worker 
386*5e7646d2SAndroid Build Coastguard Worker   if (uri && !strncmp(uri, "rss:", 4))
387*5e7646d2SAndroid Build Coastguard Worker     cupsd_start_notifier(temp);
388*5e7646d2SAndroid Build Coastguard Worker 
389*5e7646d2SAndroid Build Coastguard Worker   return (temp);
390*5e7646d2SAndroid Build Coastguard Worker }
391*5e7646d2SAndroid Build Coastguard Worker 
392*5e7646d2SAndroid Build Coastguard Worker 
393*5e7646d2SAndroid Build Coastguard Worker /*
394*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdDeleteAllSubscriptions()' - Delete all subscriptions.
395*5e7646d2SAndroid Build Coastguard Worker  */
396*5e7646d2SAndroid Build Coastguard Worker 
397*5e7646d2SAndroid Build Coastguard Worker void
cupsdDeleteAllSubscriptions(void)398*5e7646d2SAndroid Build Coastguard Worker cupsdDeleteAllSubscriptions(void)
399*5e7646d2SAndroid Build Coastguard Worker {
400*5e7646d2SAndroid Build Coastguard Worker   cupsd_subscription_t	*sub;		/* Subscription */
401*5e7646d2SAndroid Build Coastguard Worker 
402*5e7646d2SAndroid Build Coastguard Worker 
403*5e7646d2SAndroid Build Coastguard Worker   if (!Subscriptions)
404*5e7646d2SAndroid Build Coastguard Worker     return;
405*5e7646d2SAndroid Build Coastguard Worker 
406*5e7646d2SAndroid Build Coastguard Worker   for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
407*5e7646d2SAndroid Build Coastguard Worker        sub;
408*5e7646d2SAndroid Build Coastguard Worker        sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
409*5e7646d2SAndroid Build Coastguard Worker     cupsdDeleteSubscription(sub, 0);
410*5e7646d2SAndroid Build Coastguard Worker 
411*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(Subscriptions);
412*5e7646d2SAndroid Build Coastguard Worker   Subscriptions = NULL;
413*5e7646d2SAndroid Build Coastguard Worker }
414*5e7646d2SAndroid Build Coastguard Worker 
415*5e7646d2SAndroid Build Coastguard Worker 
416*5e7646d2SAndroid Build Coastguard Worker /*
417*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdDeleteSubscription()' - Delete a subscription object.
418*5e7646d2SAndroid Build Coastguard Worker  */
419*5e7646d2SAndroid Build Coastguard Worker 
420*5e7646d2SAndroid Build Coastguard Worker void
cupsdDeleteSubscription(cupsd_subscription_t * sub,int update)421*5e7646d2SAndroid Build Coastguard Worker cupsdDeleteSubscription(
422*5e7646d2SAndroid Build Coastguard Worker     cupsd_subscription_t *sub,		/* I - Subscription object */
423*5e7646d2SAndroid Build Coastguard Worker     int			 update)	/* I - 1 = update subscriptions.conf */
424*5e7646d2SAndroid Build Coastguard Worker {
425*5e7646d2SAndroid Build Coastguard Worker  /*
426*5e7646d2SAndroid Build Coastguard Worker   * Close the pipe to the notifier as needed...
427*5e7646d2SAndroid Build Coastguard Worker   */
428*5e7646d2SAndroid Build Coastguard Worker 
429*5e7646d2SAndroid Build Coastguard Worker   if (sub->pipe >= 0)
430*5e7646d2SAndroid Build Coastguard Worker     close(sub->pipe);
431*5e7646d2SAndroid Build Coastguard Worker 
432*5e7646d2SAndroid Build Coastguard Worker  /*
433*5e7646d2SAndroid Build Coastguard Worker   * Remove subscription from array...
434*5e7646d2SAndroid Build Coastguard Worker   */
435*5e7646d2SAndroid Build Coastguard Worker 
436*5e7646d2SAndroid Build Coastguard Worker   cupsArrayRemove(Subscriptions, sub);
437*5e7646d2SAndroid Build Coastguard Worker 
438*5e7646d2SAndroid Build Coastguard Worker  /*
439*5e7646d2SAndroid Build Coastguard Worker   * Free memory...
440*5e7646d2SAndroid Build Coastguard Worker   */
441*5e7646d2SAndroid Build Coastguard Worker 
442*5e7646d2SAndroid Build Coastguard Worker   cupsdClearString(&(sub->owner));
443*5e7646d2SAndroid Build Coastguard Worker   cupsdClearString(&(sub->recipient));
444*5e7646d2SAndroid Build Coastguard Worker 
445*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(sub->events);
446*5e7646d2SAndroid Build Coastguard Worker 
447*5e7646d2SAndroid Build Coastguard Worker   free(sub);
448*5e7646d2SAndroid Build Coastguard Worker 
449*5e7646d2SAndroid Build Coastguard Worker  /*
450*5e7646d2SAndroid Build Coastguard Worker   * Update the subscriptions as needed...
451*5e7646d2SAndroid Build Coastguard Worker   */
452*5e7646d2SAndroid Build Coastguard Worker 
453*5e7646d2SAndroid Build Coastguard Worker   if (update)
454*5e7646d2SAndroid Build Coastguard Worker     cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
455*5e7646d2SAndroid Build Coastguard Worker }
456*5e7646d2SAndroid Build Coastguard Worker 
457*5e7646d2SAndroid Build Coastguard Worker 
458*5e7646d2SAndroid Build Coastguard Worker /*
459*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdEventName()' - Return a single event name.
460*5e7646d2SAndroid Build Coastguard Worker  */
461*5e7646d2SAndroid Build Coastguard Worker 
462*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - Event name */
cupsdEventName(cupsd_eventmask_t event)463*5e7646d2SAndroid Build Coastguard Worker cupsdEventName(
464*5e7646d2SAndroid Build Coastguard Worker     cupsd_eventmask_t event)		/* I - Event value */
465*5e7646d2SAndroid Build Coastguard Worker {
466*5e7646d2SAndroid Build Coastguard Worker   switch (event)
467*5e7646d2SAndroid Build Coastguard Worker   {
468*5e7646d2SAndroid Build Coastguard Worker     default :
469*5e7646d2SAndroid Build Coastguard Worker 	return (NULL);
470*5e7646d2SAndroid Build Coastguard Worker 
471*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_RESTARTED :
472*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-restarted");
473*5e7646d2SAndroid Build Coastguard Worker 
474*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_SHUTDOWN :
475*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-shutdown");
476*5e7646d2SAndroid Build Coastguard Worker 
477*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_STOPPED :
478*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-stopped");
479*5e7646d2SAndroid Build Coastguard Worker 
480*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_FINISHINGS_CHANGED :
481*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-finishings-changed");
482*5e7646d2SAndroid Build Coastguard Worker 
483*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_MEDIA_CHANGED :
484*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-media-changed");
485*5e7646d2SAndroid Build Coastguard Worker 
486*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_ADDED :
487*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-added");
488*5e7646d2SAndroid Build Coastguard Worker 
489*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_DELETED :
490*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-deleted");
491*5e7646d2SAndroid Build Coastguard Worker 
492*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_MODIFIED :
493*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-modified");
494*5e7646d2SAndroid Build Coastguard Worker 
495*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED :
496*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-queue-order-changed");
497*5e7646d2SAndroid Build Coastguard Worker 
498*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_STATE :
499*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_STATE_CHANGED :
500*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-state-changed");
501*5e7646d2SAndroid Build Coastguard Worker 
502*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_CONFIG :
503*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_CONFIG_CHANGED :
504*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-config-changed");
505*5e7646d2SAndroid Build Coastguard Worker 
506*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_PRINTER_CHANGED :
507*5e7646d2SAndroid Build Coastguard Worker 	return ("printer-changed");
508*5e7646d2SAndroid Build Coastguard Worker 
509*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_JOB_CREATED :
510*5e7646d2SAndroid Build Coastguard Worker 	return ("job-created");
511*5e7646d2SAndroid Build Coastguard Worker 
512*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_JOB_COMPLETED :
513*5e7646d2SAndroid Build Coastguard Worker 	return ("job-completed");
514*5e7646d2SAndroid Build Coastguard Worker 
515*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_JOB_STOPPED :
516*5e7646d2SAndroid Build Coastguard Worker 	return ("job-stopped");
517*5e7646d2SAndroid Build Coastguard Worker 
518*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_JOB_CONFIG_CHANGED :
519*5e7646d2SAndroid Build Coastguard Worker 	return ("job-config-changed");
520*5e7646d2SAndroid Build Coastguard Worker 
521*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_JOB_PROGRESS :
522*5e7646d2SAndroid Build Coastguard Worker 	return ("job-progress");
523*5e7646d2SAndroid Build Coastguard Worker 
524*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_JOB_STATE :
525*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_JOB_STATE_CHANGED :
526*5e7646d2SAndroid Build Coastguard Worker 	return ("job-state-changed");
527*5e7646d2SAndroid Build Coastguard Worker 
528*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_SERVER_RESTARTED :
529*5e7646d2SAndroid Build Coastguard Worker 	return ("server-restarted");
530*5e7646d2SAndroid Build Coastguard Worker 
531*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_SERVER_STARTED :
532*5e7646d2SAndroid Build Coastguard Worker 	return ("server-started");
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_SERVER_STOPPED :
535*5e7646d2SAndroid Build Coastguard Worker 	return ("server-stopped");
536*5e7646d2SAndroid Build Coastguard Worker 
537*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_SERVER_AUDIT :
538*5e7646d2SAndroid Build Coastguard Worker 	return ("server-audit");
539*5e7646d2SAndroid Build Coastguard Worker 
540*5e7646d2SAndroid Build Coastguard Worker     case CUPSD_EVENT_ALL :
541*5e7646d2SAndroid Build Coastguard Worker 	return ("all");
542*5e7646d2SAndroid Build Coastguard Worker   }
543*5e7646d2SAndroid Build Coastguard Worker }
544*5e7646d2SAndroid Build Coastguard Worker 
545*5e7646d2SAndroid Build Coastguard Worker 
546*5e7646d2SAndroid Build Coastguard Worker /*
547*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdEventValue()' - Return the event mask value for a name.
548*5e7646d2SAndroid Build Coastguard Worker  */
549*5e7646d2SAndroid Build Coastguard Worker 
550*5e7646d2SAndroid Build Coastguard Worker cupsd_eventmask_t			/* O - Event mask value */
cupsdEventValue(const char * name)551*5e7646d2SAndroid Build Coastguard Worker cupsdEventValue(const char *name)	/* I - Name of event */
552*5e7646d2SAndroid Build Coastguard Worker {
553*5e7646d2SAndroid Build Coastguard Worker   if (!strcmp(name, "all"))
554*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_ALL);
555*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-restarted"))
556*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_RESTARTED);
557*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-shutdown"))
558*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_SHUTDOWN);
559*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-stopped"))
560*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_STOPPED);
561*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-finishings-changed"))
562*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_FINISHINGS_CHANGED);
563*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-media-changed"))
564*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_MEDIA_CHANGED);
565*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-added"))
566*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_ADDED);
567*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-deleted"))
568*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_DELETED);
569*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-modified"))
570*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_MODIFIED);
571*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-queue-order-changed"))
572*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED);
573*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-state-changed"))
574*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_STATE_CHANGED);
575*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-config-changed"))
576*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_CONFIG_CHANGED);
577*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "printer-changed"))
578*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_PRINTER_CHANGED);
579*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "job-created"))
580*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_JOB_CREATED);
581*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "job-completed"))
582*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_JOB_COMPLETED);
583*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "job-stopped"))
584*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_JOB_STOPPED);
585*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "job-config-changed"))
586*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_JOB_CONFIG_CHANGED);
587*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "job-progress"))
588*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_JOB_PROGRESS);
589*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "job-state-changed"))
590*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_JOB_STATE_CHANGED);
591*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "server-restarted"))
592*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_SERVER_RESTARTED);
593*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "server-started"))
594*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_SERVER_STARTED);
595*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "server-stopped"))
596*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_SERVER_STOPPED);
597*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(name, "server-audit"))
598*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_SERVER_AUDIT);
599*5e7646d2SAndroid Build Coastguard Worker   else
600*5e7646d2SAndroid Build Coastguard Worker     return (CUPSD_EVENT_NONE);
601*5e7646d2SAndroid Build Coastguard Worker }
602*5e7646d2SAndroid Build Coastguard Worker 
603*5e7646d2SAndroid Build Coastguard Worker 
604*5e7646d2SAndroid Build Coastguard Worker /*
605*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdExpireSubscriptions()' - Expire old subscription objects.
606*5e7646d2SAndroid Build Coastguard Worker  */
607*5e7646d2SAndroid Build Coastguard Worker 
608*5e7646d2SAndroid Build Coastguard Worker void
cupsdExpireSubscriptions(cupsd_printer_t * dest,cupsd_job_t * job)609*5e7646d2SAndroid Build Coastguard Worker cupsdExpireSubscriptions(
610*5e7646d2SAndroid Build Coastguard Worker     cupsd_printer_t *dest,		/* I - Printer, if any */
611*5e7646d2SAndroid Build Coastguard Worker     cupsd_job_t	    *job)		/* I - Job, if any */
612*5e7646d2SAndroid Build Coastguard Worker {
613*5e7646d2SAndroid Build Coastguard Worker   cupsd_subscription_t	*sub;		/* Current subscription */
614*5e7646d2SAndroid Build Coastguard Worker   int			update;		/* Update subscriptions.conf? */
615*5e7646d2SAndroid Build Coastguard Worker   time_t		curtime;	/* Current time */
616*5e7646d2SAndroid Build Coastguard Worker 
617*5e7646d2SAndroid Build Coastguard Worker 
618*5e7646d2SAndroid Build Coastguard Worker   if (cupsArrayCount(Subscriptions) == 0)
619*5e7646d2SAndroid Build Coastguard Worker     return;
620*5e7646d2SAndroid Build Coastguard Worker 
621*5e7646d2SAndroid Build Coastguard Worker   curtime = time(NULL);
622*5e7646d2SAndroid Build Coastguard Worker   update  = 0;
623*5e7646d2SAndroid Build Coastguard Worker 
624*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_INFO, "Expiring subscriptions...");
625*5e7646d2SAndroid Build Coastguard Worker 
626*5e7646d2SAndroid Build Coastguard Worker   for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
627*5e7646d2SAndroid Build Coastguard Worker        sub;
628*5e7646d2SAndroid Build Coastguard Worker        sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
629*5e7646d2SAndroid Build Coastguard Worker     if ((!sub->job && !dest && sub->expire && sub->expire <= curtime) ||
630*5e7646d2SAndroid Build Coastguard Worker 	(dest && sub->dest == dest) ||
631*5e7646d2SAndroid Build Coastguard Worker 	(job && sub->job == job))
632*5e7646d2SAndroid Build Coastguard Worker     {
633*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_INFO, "Subscription %d has expired...",
634*5e7646d2SAndroid Build Coastguard Worker 		      sub->id);
635*5e7646d2SAndroid Build Coastguard Worker 
636*5e7646d2SAndroid Build Coastguard Worker       cupsdDeleteSubscription(sub, 0);
637*5e7646d2SAndroid Build Coastguard Worker 
638*5e7646d2SAndroid Build Coastguard Worker       update = 1;
639*5e7646d2SAndroid Build Coastguard Worker     }
640*5e7646d2SAndroid Build Coastguard Worker 
641*5e7646d2SAndroid Build Coastguard Worker   if (update)
642*5e7646d2SAndroid Build Coastguard Worker     cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
643*5e7646d2SAndroid Build Coastguard Worker }
644*5e7646d2SAndroid Build Coastguard Worker 
645*5e7646d2SAndroid Build Coastguard Worker 
646*5e7646d2SAndroid Build Coastguard Worker /*
647*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdFindSubscription()' - Find a subscription by ID.
648*5e7646d2SAndroid Build Coastguard Worker  */
649*5e7646d2SAndroid Build Coastguard Worker 
650*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *			/* O - Subscription object */
cupsdFindSubscription(int id)651*5e7646d2SAndroid Build Coastguard Worker cupsdFindSubscription(int id)		/* I - Subscription ID */
652*5e7646d2SAndroid Build Coastguard Worker {
653*5e7646d2SAndroid Build Coastguard Worker   cupsd_subscription_t	sub;		/* Subscription template */
654*5e7646d2SAndroid Build Coastguard Worker 
655*5e7646d2SAndroid Build Coastguard Worker 
656*5e7646d2SAndroid Build Coastguard Worker   sub.id = id;
657*5e7646d2SAndroid Build Coastguard Worker 
658*5e7646d2SAndroid Build Coastguard Worker   return ((cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub));
659*5e7646d2SAndroid Build Coastguard Worker }
660*5e7646d2SAndroid Build Coastguard Worker 
661*5e7646d2SAndroid Build Coastguard Worker 
662*5e7646d2SAndroid Build Coastguard Worker /*
663*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdLoadAllSubscriptions()' - Load all subscriptions from the .conf file.
664*5e7646d2SAndroid Build Coastguard Worker  */
665*5e7646d2SAndroid Build Coastguard Worker 
666*5e7646d2SAndroid Build Coastguard Worker void
cupsdLoadAllSubscriptions(void)667*5e7646d2SAndroid Build Coastguard Worker cupsdLoadAllSubscriptions(void)
668*5e7646d2SAndroid Build Coastguard Worker {
669*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
670*5e7646d2SAndroid Build Coastguard Worker   cups_file_t		*fp;		/* subscriptions.conf file */
671*5e7646d2SAndroid Build Coastguard Worker   int			linenum;	/* Current line number */
672*5e7646d2SAndroid Build Coastguard Worker   char			line[1024],	/* Line from file */
673*5e7646d2SAndroid Build Coastguard Worker 			*value,		/* Pointer to value */
674*5e7646d2SAndroid Build Coastguard Worker 			*valueptr;	/* Pointer into value */
675*5e7646d2SAndroid Build Coastguard Worker   cupsd_subscription_t	*sub;		/* Current subscription */
676*5e7646d2SAndroid Build Coastguard Worker   int			hex;		/* Non-zero if reading hex data */
677*5e7646d2SAndroid Build Coastguard Worker   int			delete_sub;	/* Delete subscription? */
678*5e7646d2SAndroid Build Coastguard Worker 
679*5e7646d2SAndroid Build Coastguard Worker 
680*5e7646d2SAndroid Build Coastguard Worker  /*
681*5e7646d2SAndroid Build Coastguard Worker   * Open the subscriptions.conf file...
682*5e7646d2SAndroid Build Coastguard Worker   */
683*5e7646d2SAndroid Build Coastguard Worker 
684*5e7646d2SAndroid Build Coastguard Worker   snprintf(line, sizeof(line), "%s/subscriptions.conf", ServerRoot);
685*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsdOpenConfFile(line)) == NULL)
686*5e7646d2SAndroid Build Coastguard Worker     return;
687*5e7646d2SAndroid Build Coastguard Worker 
688*5e7646d2SAndroid Build Coastguard Worker  /*
689*5e7646d2SAndroid Build Coastguard Worker   * Read all of the lines from the file...
690*5e7646d2SAndroid Build Coastguard Worker   */
691*5e7646d2SAndroid Build Coastguard Worker 
692*5e7646d2SAndroid Build Coastguard Worker   linenum    = 0;
693*5e7646d2SAndroid Build Coastguard Worker   sub	     = NULL;
694*5e7646d2SAndroid Build Coastguard Worker   delete_sub = 0;
695*5e7646d2SAndroid Build Coastguard Worker 
696*5e7646d2SAndroid Build Coastguard Worker   while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
697*5e7646d2SAndroid Build Coastguard Worker   {
698*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(line, "NextSubscriptionId") && value)
699*5e7646d2SAndroid Build Coastguard Worker     {
700*5e7646d2SAndroid Build Coastguard Worker      /*
701*5e7646d2SAndroid Build Coastguard Worker       * NextSubscriptionId NNN
702*5e7646d2SAndroid Build Coastguard Worker       */
703*5e7646d2SAndroid Build Coastguard Worker 
704*5e7646d2SAndroid Build Coastguard Worker       i = atoi(value);
705*5e7646d2SAndroid Build Coastguard Worker       if (i >= NextSubscriptionId && i > 0)
706*5e7646d2SAndroid Build Coastguard Worker 	NextSubscriptionId = i;
707*5e7646d2SAndroid Build Coastguard Worker     }
708*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "<Subscription"))
709*5e7646d2SAndroid Build Coastguard Worker     {
710*5e7646d2SAndroid Build Coastguard Worker      /*
711*5e7646d2SAndroid Build Coastguard Worker       * <Subscription #>
712*5e7646d2SAndroid Build Coastguard Worker       */
713*5e7646d2SAndroid Build Coastguard Worker 
714*5e7646d2SAndroid Build Coastguard Worker       if (!sub && value && isdigit(value[0] & 255))
715*5e7646d2SAndroid Build Coastguard Worker       {
716*5e7646d2SAndroid Build Coastguard Worker 	sub = cupsdAddSubscription(CUPSD_EVENT_NONE, NULL, NULL, NULL,
717*5e7646d2SAndroid Build Coastguard Worker 				   atoi(value));
718*5e7646d2SAndroid Build Coastguard Worker       }
719*5e7646d2SAndroid Build Coastguard Worker       else
720*5e7646d2SAndroid Build Coastguard Worker       {
721*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
722*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
723*5e7646d2SAndroid Build Coastguard Worker 			linenum);
724*5e7646d2SAndroid Build Coastguard Worker 	break;
725*5e7646d2SAndroid Build Coastguard Worker       }
726*5e7646d2SAndroid Build Coastguard Worker     }
727*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "</Subscription>"))
728*5e7646d2SAndroid Build Coastguard Worker     {
729*5e7646d2SAndroid Build Coastguard Worker       if (!sub)
730*5e7646d2SAndroid Build Coastguard Worker       {
731*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
732*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
733*5e7646d2SAndroid Build Coastguard Worker 			linenum);
734*5e7646d2SAndroid Build Coastguard Worker 	break;
735*5e7646d2SAndroid Build Coastguard Worker       }
736*5e7646d2SAndroid Build Coastguard Worker 
737*5e7646d2SAndroid Build Coastguard Worker       if (delete_sub)
738*5e7646d2SAndroid Build Coastguard Worker 	cupsdDeleteSubscription(sub, 0);
739*5e7646d2SAndroid Build Coastguard Worker 
740*5e7646d2SAndroid Build Coastguard Worker       sub	 = NULL;
741*5e7646d2SAndroid Build Coastguard Worker       delete_sub = 0;
742*5e7646d2SAndroid Build Coastguard Worker     }
743*5e7646d2SAndroid Build Coastguard Worker     else if (!sub)
744*5e7646d2SAndroid Build Coastguard Worker     {
745*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_ERROR,
746*5e7646d2SAndroid Build Coastguard Worker 		      "Syntax error on line %d of subscriptions.conf.",
747*5e7646d2SAndroid Build Coastguard Worker 		      linenum);
748*5e7646d2SAndroid Build Coastguard Worker     }
749*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Events"))
750*5e7646d2SAndroid Build Coastguard Worker     {
751*5e7646d2SAndroid Build Coastguard Worker      /*
752*5e7646d2SAndroid Build Coastguard Worker       * Events name
753*5e7646d2SAndroid Build Coastguard Worker       * Events name name name ...
754*5e7646d2SAndroid Build Coastguard Worker       */
755*5e7646d2SAndroid Build Coastguard Worker 
756*5e7646d2SAndroid Build Coastguard Worker       if (!value)
757*5e7646d2SAndroid Build Coastguard Worker       {
758*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
759*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
760*5e7646d2SAndroid Build Coastguard Worker 			linenum);
761*5e7646d2SAndroid Build Coastguard Worker 	break;
762*5e7646d2SAndroid Build Coastguard Worker       }
763*5e7646d2SAndroid Build Coastguard Worker 
764*5e7646d2SAndroid Build Coastguard Worker       while (*value)
765*5e7646d2SAndroid Build Coastguard Worker       {
766*5e7646d2SAndroid Build Coastguard Worker        /*
767*5e7646d2SAndroid Build Coastguard Worker 	* Separate event names...
768*5e7646d2SAndroid Build Coastguard Worker 	*/
769*5e7646d2SAndroid Build Coastguard Worker 
770*5e7646d2SAndroid Build Coastguard Worker 	for (valueptr = value; !isspace(*valueptr) && *valueptr; valueptr ++);
771*5e7646d2SAndroid Build Coastguard Worker 
772*5e7646d2SAndroid Build Coastguard Worker 	while (isspace(*valueptr & 255))
773*5e7646d2SAndroid Build Coastguard Worker 	  *valueptr++ = '\0';
774*5e7646d2SAndroid Build Coastguard Worker 
775*5e7646d2SAndroid Build Coastguard Worker        /*
776*5e7646d2SAndroid Build Coastguard Worker 	* See if the name exists...
777*5e7646d2SAndroid Build Coastguard Worker 	*/
778*5e7646d2SAndroid Build Coastguard Worker 
779*5e7646d2SAndroid Build Coastguard Worker 	if ((sub->mask |= cupsdEventValue(value)) == CUPSD_EVENT_NONE)
780*5e7646d2SAndroid Build Coastguard Worker 	{
781*5e7646d2SAndroid Build Coastguard Worker 	  cupsdLogMessage(CUPSD_LOG_ERROR,
782*5e7646d2SAndroid Build Coastguard Worker 			  "Unknown event name \'%s\' on line %d of subscriptions.conf.",
783*5e7646d2SAndroid Build Coastguard Worker 			  value, linenum);
784*5e7646d2SAndroid Build Coastguard Worker 	  break;
785*5e7646d2SAndroid Build Coastguard Worker 	}
786*5e7646d2SAndroid Build Coastguard Worker 
787*5e7646d2SAndroid Build Coastguard Worker 	value = valueptr;
788*5e7646d2SAndroid Build Coastguard Worker       }
789*5e7646d2SAndroid Build Coastguard Worker     }
790*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Owner"))
791*5e7646d2SAndroid Build Coastguard Worker     {
792*5e7646d2SAndroid Build Coastguard Worker      /*
793*5e7646d2SAndroid Build Coastguard Worker       * Owner
794*5e7646d2SAndroid Build Coastguard Worker       */
795*5e7646d2SAndroid Build Coastguard Worker 
796*5e7646d2SAndroid Build Coastguard Worker       if (value)
797*5e7646d2SAndroid Build Coastguard Worker 	cupsdSetString(&sub->owner, value);
798*5e7646d2SAndroid Build Coastguard Worker       else
799*5e7646d2SAndroid Build Coastguard Worker       {
800*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
801*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
802*5e7646d2SAndroid Build Coastguard Worker 			linenum);
803*5e7646d2SAndroid Build Coastguard Worker 	break;
804*5e7646d2SAndroid Build Coastguard Worker       }
805*5e7646d2SAndroid Build Coastguard Worker     }
806*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Recipient"))
807*5e7646d2SAndroid Build Coastguard Worker     {
808*5e7646d2SAndroid Build Coastguard Worker      /*
809*5e7646d2SAndroid Build Coastguard Worker       * Recipient uri
810*5e7646d2SAndroid Build Coastguard Worker       */
811*5e7646d2SAndroid Build Coastguard Worker 
812*5e7646d2SAndroid Build Coastguard Worker       if (value)
813*5e7646d2SAndroid Build Coastguard Worker 	cupsdSetString(&sub->recipient, value);
814*5e7646d2SAndroid Build Coastguard Worker       else
815*5e7646d2SAndroid Build Coastguard Worker       {
816*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
817*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
818*5e7646d2SAndroid Build Coastguard Worker 			linenum);
819*5e7646d2SAndroid Build Coastguard Worker 	break;
820*5e7646d2SAndroid Build Coastguard Worker       }
821*5e7646d2SAndroid Build Coastguard Worker     }
822*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "JobId"))
823*5e7646d2SAndroid Build Coastguard Worker     {
824*5e7646d2SAndroid Build Coastguard Worker      /*
825*5e7646d2SAndroid Build Coastguard Worker       * JobId #
826*5e7646d2SAndroid Build Coastguard Worker       */
827*5e7646d2SAndroid Build Coastguard Worker 
828*5e7646d2SAndroid Build Coastguard Worker       if (value && isdigit(*value & 255))
829*5e7646d2SAndroid Build Coastguard Worker       {
830*5e7646d2SAndroid Build Coastguard Worker 	if ((sub->job = cupsdFindJob(atoi(value))) == NULL)
831*5e7646d2SAndroid Build Coastguard Worker 	{
832*5e7646d2SAndroid Build Coastguard Worker 	  cupsdLogMessage(CUPSD_LOG_ERROR,
833*5e7646d2SAndroid Build Coastguard Worker 			  "Job %s not found on line %d of subscriptions.conf.",
834*5e7646d2SAndroid Build Coastguard Worker 			  value, linenum);
835*5e7646d2SAndroid Build Coastguard Worker 	  delete_sub = 1;
836*5e7646d2SAndroid Build Coastguard Worker 	}
837*5e7646d2SAndroid Build Coastguard Worker       }
838*5e7646d2SAndroid Build Coastguard Worker       else
839*5e7646d2SAndroid Build Coastguard Worker       {
840*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
841*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
842*5e7646d2SAndroid Build Coastguard Worker 			linenum);
843*5e7646d2SAndroid Build Coastguard Worker 	break;
844*5e7646d2SAndroid Build Coastguard Worker       }
845*5e7646d2SAndroid Build Coastguard Worker     }
846*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "PrinterName"))
847*5e7646d2SAndroid Build Coastguard Worker     {
848*5e7646d2SAndroid Build Coastguard Worker      /*
849*5e7646d2SAndroid Build Coastguard Worker       * PrinterName name
850*5e7646d2SAndroid Build Coastguard Worker       */
851*5e7646d2SAndroid Build Coastguard Worker 
852*5e7646d2SAndroid Build Coastguard Worker       if (value)
853*5e7646d2SAndroid Build Coastguard Worker       {
854*5e7646d2SAndroid Build Coastguard Worker 	if ((sub->dest = cupsdFindDest(value)) == NULL)
855*5e7646d2SAndroid Build Coastguard Worker 	{
856*5e7646d2SAndroid Build Coastguard Worker 	  cupsdLogMessage(CUPSD_LOG_ERROR,
857*5e7646d2SAndroid Build Coastguard Worker 			  "Printer \'%s\' not found on line %d of subscriptions.conf.",
858*5e7646d2SAndroid Build Coastguard Worker 			  value, linenum);
859*5e7646d2SAndroid Build Coastguard Worker 	  delete_sub = 1;
860*5e7646d2SAndroid Build Coastguard Worker 	}
861*5e7646d2SAndroid Build Coastguard Worker       }
862*5e7646d2SAndroid Build Coastguard Worker       else
863*5e7646d2SAndroid Build Coastguard Worker       {
864*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
865*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
866*5e7646d2SAndroid Build Coastguard Worker 			linenum);
867*5e7646d2SAndroid Build Coastguard Worker 	break;
868*5e7646d2SAndroid Build Coastguard Worker       }
869*5e7646d2SAndroid Build Coastguard Worker     }
870*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "UserData"))
871*5e7646d2SAndroid Build Coastguard Worker     {
872*5e7646d2SAndroid Build Coastguard Worker      /*
873*5e7646d2SAndroid Build Coastguard Worker       * UserData encoded-string
874*5e7646d2SAndroid Build Coastguard Worker       */
875*5e7646d2SAndroid Build Coastguard Worker 
876*5e7646d2SAndroid Build Coastguard Worker       if (value)
877*5e7646d2SAndroid Build Coastguard Worker       {
878*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0, valueptr = value, hex = 0; i < 63 && *valueptr; i ++)
879*5e7646d2SAndroid Build Coastguard Worker 	{
880*5e7646d2SAndroid Build Coastguard Worker 	  if (*valueptr == '<' && !hex)
881*5e7646d2SAndroid Build Coastguard Worker 	  {
882*5e7646d2SAndroid Build Coastguard Worker 	    hex = 1;
883*5e7646d2SAndroid Build Coastguard Worker 	    valueptr ++;
884*5e7646d2SAndroid Build Coastguard Worker 	  }
885*5e7646d2SAndroid Build Coastguard Worker 
886*5e7646d2SAndroid Build Coastguard Worker 	  if (hex)
887*5e7646d2SAndroid Build Coastguard Worker 	  {
888*5e7646d2SAndroid Build Coastguard Worker 	    if (isxdigit(valueptr[0]) && isxdigit(valueptr[1]))
889*5e7646d2SAndroid Build Coastguard Worker 	    {
890*5e7646d2SAndroid Build Coastguard Worker 	      if (isdigit(valueptr[0]))
891*5e7646d2SAndroid Build Coastguard Worker 		sub->user_data[i] = (unsigned char)((valueptr[0] - '0') << 4);
892*5e7646d2SAndroid Build Coastguard Worker 	      else
893*5e7646d2SAndroid Build Coastguard Worker 		sub->user_data[i] = (unsigned char)((tolower(valueptr[0]) - 'a' + 10) << 4);
894*5e7646d2SAndroid Build Coastguard Worker 
895*5e7646d2SAndroid Build Coastguard Worker 	      if (isdigit(valueptr[1]))
896*5e7646d2SAndroid Build Coastguard Worker 		sub->user_data[i] |= valueptr[1] - '0';
897*5e7646d2SAndroid Build Coastguard Worker 	      else
898*5e7646d2SAndroid Build Coastguard Worker 		sub->user_data[i] |= tolower(valueptr[1]) - 'a' + 10;
899*5e7646d2SAndroid Build Coastguard Worker 
900*5e7646d2SAndroid Build Coastguard Worker 	      valueptr += 2;
901*5e7646d2SAndroid Build Coastguard Worker 
902*5e7646d2SAndroid Build Coastguard Worker 	      if (*valueptr == '>')
903*5e7646d2SAndroid Build Coastguard Worker 	      {
904*5e7646d2SAndroid Build Coastguard Worker 		hex = 0;
905*5e7646d2SAndroid Build Coastguard Worker 		valueptr ++;
906*5e7646d2SAndroid Build Coastguard Worker 	      }
907*5e7646d2SAndroid Build Coastguard Worker 	    }
908*5e7646d2SAndroid Build Coastguard Worker 	    else
909*5e7646d2SAndroid Build Coastguard Worker 	      break;
910*5e7646d2SAndroid Build Coastguard Worker 	  }
911*5e7646d2SAndroid Build Coastguard Worker 	  else
912*5e7646d2SAndroid Build Coastguard Worker 	    sub->user_data[i] = (unsigned char)*valueptr++;
913*5e7646d2SAndroid Build Coastguard Worker 	}
914*5e7646d2SAndroid Build Coastguard Worker 
915*5e7646d2SAndroid Build Coastguard Worker 	if (*valueptr)
916*5e7646d2SAndroid Build Coastguard Worker 	{
917*5e7646d2SAndroid Build Coastguard Worker 	  cupsdLogMessage(CUPSD_LOG_ERROR,
918*5e7646d2SAndroid Build Coastguard Worker 			  "Bad UserData \'%s\' on line %d of subscriptions.conf.",
919*5e7646d2SAndroid Build Coastguard Worker 			  value, linenum);
920*5e7646d2SAndroid Build Coastguard Worker 	}
921*5e7646d2SAndroid Build Coastguard Worker 	else
922*5e7646d2SAndroid Build Coastguard Worker 	  sub->user_data_len = i;
923*5e7646d2SAndroid Build Coastguard Worker       }
924*5e7646d2SAndroid Build Coastguard Worker       else
925*5e7646d2SAndroid Build Coastguard Worker       {
926*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
927*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
928*5e7646d2SAndroid Build Coastguard Worker 			linenum);
929*5e7646d2SAndroid Build Coastguard Worker 	break;
930*5e7646d2SAndroid Build Coastguard Worker       }
931*5e7646d2SAndroid Build Coastguard Worker     }
932*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "LeaseDuration"))
933*5e7646d2SAndroid Build Coastguard Worker     {
934*5e7646d2SAndroid Build Coastguard Worker      /*
935*5e7646d2SAndroid Build Coastguard Worker       * LeaseDuration #
936*5e7646d2SAndroid Build Coastguard Worker       */
937*5e7646d2SAndroid Build Coastguard Worker 
938*5e7646d2SAndroid Build Coastguard Worker       if (value && isdigit(*value & 255))
939*5e7646d2SAndroid Build Coastguard Worker       {
940*5e7646d2SAndroid Build Coastguard Worker 	sub->lease  = atoi(value);
941*5e7646d2SAndroid Build Coastguard Worker 	sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
942*5e7646d2SAndroid Build Coastguard Worker       }
943*5e7646d2SAndroid Build Coastguard Worker       else
944*5e7646d2SAndroid Build Coastguard Worker       {
945*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
946*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
947*5e7646d2SAndroid Build Coastguard Worker 			linenum);
948*5e7646d2SAndroid Build Coastguard Worker 	break;
949*5e7646d2SAndroid Build Coastguard Worker       }
950*5e7646d2SAndroid Build Coastguard Worker     }
951*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Interval"))
952*5e7646d2SAndroid Build Coastguard Worker     {
953*5e7646d2SAndroid Build Coastguard Worker      /*
954*5e7646d2SAndroid Build Coastguard Worker       * Interval #
955*5e7646d2SAndroid Build Coastguard Worker       */
956*5e7646d2SAndroid Build Coastguard Worker 
957*5e7646d2SAndroid Build Coastguard Worker       if (value && isdigit(*value & 255))
958*5e7646d2SAndroid Build Coastguard Worker 	sub->interval = atoi(value);
959*5e7646d2SAndroid Build Coastguard Worker       else
960*5e7646d2SAndroid Build Coastguard Worker       {
961*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
962*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
963*5e7646d2SAndroid Build Coastguard Worker 			linenum);
964*5e7646d2SAndroid Build Coastguard Worker 	break;
965*5e7646d2SAndroid Build Coastguard Worker       }
966*5e7646d2SAndroid Build Coastguard Worker     }
967*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "ExpirationTime"))
968*5e7646d2SAndroid Build Coastguard Worker     {
969*5e7646d2SAndroid Build Coastguard Worker      /*
970*5e7646d2SAndroid Build Coastguard Worker       * ExpirationTime #
971*5e7646d2SAndroid Build Coastguard Worker       */
972*5e7646d2SAndroid Build Coastguard Worker 
973*5e7646d2SAndroid Build Coastguard Worker       if (value && isdigit(*value & 255))
974*5e7646d2SAndroid Build Coastguard Worker 	sub->expire = atoi(value);
975*5e7646d2SAndroid Build Coastguard Worker       else
976*5e7646d2SAndroid Build Coastguard Worker       {
977*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
978*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
979*5e7646d2SAndroid Build Coastguard Worker 			linenum);
980*5e7646d2SAndroid Build Coastguard Worker 	break;
981*5e7646d2SAndroid Build Coastguard Worker       }
982*5e7646d2SAndroid Build Coastguard Worker     }
983*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "NextEventId"))
984*5e7646d2SAndroid Build Coastguard Worker     {
985*5e7646d2SAndroid Build Coastguard Worker      /*
986*5e7646d2SAndroid Build Coastguard Worker       * NextEventId #
987*5e7646d2SAndroid Build Coastguard Worker       */
988*5e7646d2SAndroid Build Coastguard Worker 
989*5e7646d2SAndroid Build Coastguard Worker       if (value && isdigit(*value & 255))
990*5e7646d2SAndroid Build Coastguard Worker 	sub->next_event_id = sub->first_event_id = atoi(value);
991*5e7646d2SAndroid Build Coastguard Worker       else
992*5e7646d2SAndroid Build Coastguard Worker       {
993*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
994*5e7646d2SAndroid Build Coastguard Worker 			"Syntax error on line %d of subscriptions.conf.",
995*5e7646d2SAndroid Build Coastguard Worker 			linenum);
996*5e7646d2SAndroid Build Coastguard Worker 	break;
997*5e7646d2SAndroid Build Coastguard Worker       }
998*5e7646d2SAndroid Build Coastguard Worker     }
999*5e7646d2SAndroid Build Coastguard Worker     else
1000*5e7646d2SAndroid Build Coastguard Worker     {
1001*5e7646d2SAndroid Build Coastguard Worker      /*
1002*5e7646d2SAndroid Build Coastguard Worker       * Something else we don't understand...
1003*5e7646d2SAndroid Build Coastguard Worker       */
1004*5e7646d2SAndroid Build Coastguard Worker 
1005*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_ERROR,
1006*5e7646d2SAndroid Build Coastguard Worker 		      "Unknown configuration directive %s on line %d of subscriptions.conf.",
1007*5e7646d2SAndroid Build Coastguard Worker 		      line, linenum);
1008*5e7646d2SAndroid Build Coastguard Worker     }
1009*5e7646d2SAndroid Build Coastguard Worker   }
1010*5e7646d2SAndroid Build Coastguard Worker 
1011*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(fp);
1012*5e7646d2SAndroid Build Coastguard Worker }
1013*5e7646d2SAndroid Build Coastguard Worker 
1014*5e7646d2SAndroid Build Coastguard Worker 
1015*5e7646d2SAndroid Build Coastguard Worker /*
1016*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdSaveAllSubscriptions()' - Save all subscriptions to the .conf file.
1017*5e7646d2SAndroid Build Coastguard Worker  */
1018*5e7646d2SAndroid Build Coastguard Worker 
1019*5e7646d2SAndroid Build Coastguard Worker void
cupsdSaveAllSubscriptions(void)1020*5e7646d2SAndroid Build Coastguard Worker cupsdSaveAllSubscriptions(void)
1021*5e7646d2SAndroid Build Coastguard Worker {
1022*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
1023*5e7646d2SAndroid Build Coastguard Worker   cups_file_t		*fp;		/* subscriptions.conf file */
1024*5e7646d2SAndroid Build Coastguard Worker   char			filename[1024]; /* subscriptions.conf filename */
1025*5e7646d2SAndroid Build Coastguard Worker   cupsd_subscription_t	*sub;		/* Current subscription */
1026*5e7646d2SAndroid Build Coastguard Worker   unsigned		mask;		/* Current event mask */
1027*5e7646d2SAndroid Build Coastguard Worker   const char		*name;		/* Current event name */
1028*5e7646d2SAndroid Build Coastguard Worker   int			hex;		/* Non-zero if we are writing hex data */
1029*5e7646d2SAndroid Build Coastguard Worker 
1030*5e7646d2SAndroid Build Coastguard Worker 
1031*5e7646d2SAndroid Build Coastguard Worker  /*
1032*5e7646d2SAndroid Build Coastguard Worker   * Create the subscriptions.conf file...
1033*5e7646d2SAndroid Build Coastguard Worker   */
1034*5e7646d2SAndroid Build Coastguard Worker 
1035*5e7646d2SAndroid Build Coastguard Worker   snprintf(filename, sizeof(filename), "%s/subscriptions.conf", ServerRoot);
1036*5e7646d2SAndroid Build Coastguard Worker 
1037*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm)) == NULL)
1038*5e7646d2SAndroid Build Coastguard Worker     return;
1039*5e7646d2SAndroid Build Coastguard Worker 
1040*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_INFO, "Saving subscriptions.conf...");
1041*5e7646d2SAndroid Build Coastguard Worker 
1042*5e7646d2SAndroid Build Coastguard Worker  /*
1043*5e7646d2SAndroid Build Coastguard Worker   * Write a small header to the file...
1044*5e7646d2SAndroid Build Coastguard Worker   */
1045*5e7646d2SAndroid Build Coastguard Worker 
1046*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "# Subscription configuration file for " CUPS_SVERSION "\n");
1047*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "# Written by cupsd\n");
1048*5e7646d2SAndroid Build Coastguard Worker 
1049*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "NextSubscriptionId %d\n", NextSubscriptionId);
1050*5e7646d2SAndroid Build Coastguard Worker 
1051*5e7646d2SAndroid Build Coastguard Worker  /*
1052*5e7646d2SAndroid Build Coastguard Worker   * Write every subscription known to the system...
1053*5e7646d2SAndroid Build Coastguard Worker   */
1054*5e7646d2SAndroid Build Coastguard Worker 
1055*5e7646d2SAndroid Build Coastguard Worker   for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
1056*5e7646d2SAndroid Build Coastguard Worker        sub;
1057*5e7646d2SAndroid Build Coastguard Worker        sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
1058*5e7646d2SAndroid Build Coastguard Worker   {
1059*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "<Subscription %d>\n", sub->id);
1060*5e7646d2SAndroid Build Coastguard Worker 
1061*5e7646d2SAndroid Build Coastguard Worker     if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL)
1062*5e7646d2SAndroid Build Coastguard Worker     {
1063*5e7646d2SAndroid Build Coastguard Worker      /*
1064*5e7646d2SAndroid Build Coastguard Worker       * Simple event list...
1065*5e7646d2SAndroid Build Coastguard Worker       */
1066*5e7646d2SAndroid Build Coastguard Worker 
1067*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "Events %s\n", name);
1068*5e7646d2SAndroid Build Coastguard Worker     }
1069*5e7646d2SAndroid Build Coastguard Worker     else
1070*5e7646d2SAndroid Build Coastguard Worker     {
1071*5e7646d2SAndroid Build Coastguard Worker      /*
1072*5e7646d2SAndroid Build Coastguard Worker       * Complex event list...
1073*5e7646d2SAndroid Build Coastguard Worker       */
1074*5e7646d2SAndroid Build Coastguard Worker 
1075*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "Events");
1076*5e7646d2SAndroid Build Coastguard Worker 
1077*5e7646d2SAndroid Build Coastguard Worker       for (mask = 1; mask < CUPSD_EVENT_ALL; mask <<= 1)
1078*5e7646d2SAndroid Build Coastguard Worker 	if (sub->mask & mask)
1079*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(fp, " %s", cupsdEventName((cupsd_eventmask_t)mask));
1080*5e7646d2SAndroid Build Coastguard Worker 
1081*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "\n");
1082*5e7646d2SAndroid Build Coastguard Worker     }
1083*5e7646d2SAndroid Build Coastguard Worker 
1084*5e7646d2SAndroid Build Coastguard Worker     if (sub->owner)
1085*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "Owner %s\n", sub->owner);
1086*5e7646d2SAndroid Build Coastguard Worker     if (sub->recipient)
1087*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "Recipient %s\n", sub->recipient);
1088*5e7646d2SAndroid Build Coastguard Worker     if (sub->job)
1089*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "JobId %d\n", sub->job->id);
1090*5e7646d2SAndroid Build Coastguard Worker     if (sub->dest)
1091*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "PrinterName %s\n", sub->dest->name);
1092*5e7646d2SAndroid Build Coastguard Worker 
1093*5e7646d2SAndroid Build Coastguard Worker     if (sub->user_data_len > 0)
1094*5e7646d2SAndroid Build Coastguard Worker     {
1095*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "UserData ");
1096*5e7646d2SAndroid Build Coastguard Worker 
1097*5e7646d2SAndroid Build Coastguard Worker       for (i = 0, hex = 0; i < sub->user_data_len; i ++)
1098*5e7646d2SAndroid Build Coastguard Worker       {
1099*5e7646d2SAndroid Build Coastguard Worker 	if (sub->user_data[i] < ' ' ||
1100*5e7646d2SAndroid Build Coastguard Worker 	    sub->user_data[i] > 0x7f ||
1101*5e7646d2SAndroid Build Coastguard Worker 	    sub->user_data[i] == '<')
1102*5e7646d2SAndroid Build Coastguard Worker 	{
1103*5e7646d2SAndroid Build Coastguard Worker 	  if (!hex)
1104*5e7646d2SAndroid Build Coastguard Worker 	  {
1105*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(fp, "<%02X", sub->user_data[i]);
1106*5e7646d2SAndroid Build Coastguard Worker 	    hex = 1;
1107*5e7646d2SAndroid Build Coastguard Worker 	  }
1108*5e7646d2SAndroid Build Coastguard Worker 	  else
1109*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(fp, "%02X", sub->user_data[i]);
1110*5e7646d2SAndroid Build Coastguard Worker 	}
1111*5e7646d2SAndroid Build Coastguard Worker 	else
1112*5e7646d2SAndroid Build Coastguard Worker 	{
1113*5e7646d2SAndroid Build Coastguard Worker 	  if (hex)
1114*5e7646d2SAndroid Build Coastguard Worker 	  {
1115*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(fp, ">%c", sub->user_data[i]);
1116*5e7646d2SAndroid Build Coastguard Worker 	    hex = 0;
1117*5e7646d2SAndroid Build Coastguard Worker 	  }
1118*5e7646d2SAndroid Build Coastguard Worker 	  else
1119*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePutChar(fp, sub->user_data[i]);
1120*5e7646d2SAndroid Build Coastguard Worker 	}
1121*5e7646d2SAndroid Build Coastguard Worker       }
1122*5e7646d2SAndroid Build Coastguard Worker 
1123*5e7646d2SAndroid Build Coastguard Worker       if (hex)
1124*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePuts(fp, ">\n");
1125*5e7646d2SAndroid Build Coastguard Worker       else
1126*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePutChar(fp, '\n');
1127*5e7646d2SAndroid Build Coastguard Worker     }
1128*5e7646d2SAndroid Build Coastguard Worker 
1129*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "LeaseDuration %d\n", sub->lease);
1130*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Interval %d\n", sub->interval);
1131*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "ExpirationTime %ld\n", (long)sub->expire);
1132*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "NextEventId %d\n", sub->next_event_id);
1133*5e7646d2SAndroid Build Coastguard Worker 
1134*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "</Subscription>\n");
1135*5e7646d2SAndroid Build Coastguard Worker   }
1136*5e7646d2SAndroid Build Coastguard Worker 
1137*5e7646d2SAndroid Build Coastguard Worker   cupsdCloseCreatedConfFile(fp, filename);
1138*5e7646d2SAndroid Build Coastguard Worker }
1139*5e7646d2SAndroid Build Coastguard Worker 
1140*5e7646d2SAndroid Build Coastguard Worker 
1141*5e7646d2SAndroid Build Coastguard Worker /*
1142*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdStopAllNotifiers()' - Stop all notifier processes.
1143*5e7646d2SAndroid Build Coastguard Worker  */
1144*5e7646d2SAndroid Build Coastguard Worker 
1145*5e7646d2SAndroid Build Coastguard Worker void
cupsdStopAllNotifiers(void)1146*5e7646d2SAndroid Build Coastguard Worker cupsdStopAllNotifiers(void)
1147*5e7646d2SAndroid Build Coastguard Worker {
1148*5e7646d2SAndroid Build Coastguard Worker   cupsd_subscription_t	*sub;		/* Current subscription */
1149*5e7646d2SAndroid Build Coastguard Worker 
1150*5e7646d2SAndroid Build Coastguard Worker 
1151*5e7646d2SAndroid Build Coastguard Worker  /*
1152*5e7646d2SAndroid Build Coastguard Worker   * See if we have started any notifiers...
1153*5e7646d2SAndroid Build Coastguard Worker   */
1154*5e7646d2SAndroid Build Coastguard Worker 
1155*5e7646d2SAndroid Build Coastguard Worker   if (!NotifierStatusBuffer)
1156*5e7646d2SAndroid Build Coastguard Worker     return;
1157*5e7646d2SAndroid Build Coastguard Worker 
1158*5e7646d2SAndroid Build Coastguard Worker  /*
1159*5e7646d2SAndroid Build Coastguard Worker   * Yes, kill any processes that are left...
1160*5e7646d2SAndroid Build Coastguard Worker   */
1161*5e7646d2SAndroid Build Coastguard Worker 
1162*5e7646d2SAndroid Build Coastguard Worker   for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
1163*5e7646d2SAndroid Build Coastguard Worker        sub;
1164*5e7646d2SAndroid Build Coastguard Worker        sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
1165*5e7646d2SAndroid Build Coastguard Worker     if (sub->pid)
1166*5e7646d2SAndroid Build Coastguard Worker     {
1167*5e7646d2SAndroid Build Coastguard Worker       cupsdEndProcess(sub->pid, 0);
1168*5e7646d2SAndroid Build Coastguard Worker 
1169*5e7646d2SAndroid Build Coastguard Worker       close(sub->pipe);
1170*5e7646d2SAndroid Build Coastguard Worker       sub->pipe = -1;
1171*5e7646d2SAndroid Build Coastguard Worker     }
1172*5e7646d2SAndroid Build Coastguard Worker 
1173*5e7646d2SAndroid Build Coastguard Worker  /*
1174*5e7646d2SAndroid Build Coastguard Worker   * Close the status pipes...
1175*5e7646d2SAndroid Build Coastguard Worker   */
1176*5e7646d2SAndroid Build Coastguard Worker 
1177*5e7646d2SAndroid Build Coastguard Worker   if (NotifierPipes[0] >= 0)
1178*5e7646d2SAndroid Build Coastguard Worker   {
1179*5e7646d2SAndroid Build Coastguard Worker     cupsdRemoveSelect(NotifierPipes[0]);
1180*5e7646d2SAndroid Build Coastguard Worker 
1181*5e7646d2SAndroid Build Coastguard Worker     cupsdStatBufDelete(NotifierStatusBuffer);
1182*5e7646d2SAndroid Build Coastguard Worker 
1183*5e7646d2SAndroid Build Coastguard Worker     close(NotifierPipes[0]);
1184*5e7646d2SAndroid Build Coastguard Worker     close(NotifierPipes[1]);
1185*5e7646d2SAndroid Build Coastguard Worker 
1186*5e7646d2SAndroid Build Coastguard Worker     NotifierPipes[0] = -1;
1187*5e7646d2SAndroid Build Coastguard Worker     NotifierPipes[1] = -1;
1188*5e7646d2SAndroid Build Coastguard Worker     NotifierStatusBuffer = NULL;
1189*5e7646d2SAndroid Build Coastguard Worker   }
1190*5e7646d2SAndroid Build Coastguard Worker }
1191*5e7646d2SAndroid Build Coastguard Worker 
1192*5e7646d2SAndroid Build Coastguard Worker 
1193*5e7646d2SAndroid Build Coastguard Worker /*
1194*5e7646d2SAndroid Build Coastguard Worker  * 'cupsd_compare_subscriptions()' - Compare two subscriptions.
1195*5e7646d2SAndroid Build Coastguard Worker  */
1196*5e7646d2SAndroid Build Coastguard Worker 
1197*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
cupsd_compare_subscriptions(cupsd_subscription_t * first,cupsd_subscription_t * second,void * unused)1198*5e7646d2SAndroid Build Coastguard Worker cupsd_compare_subscriptions(
1199*5e7646d2SAndroid Build Coastguard Worker     cupsd_subscription_t *first,	/* I - First subscription object */
1200*5e7646d2SAndroid Build Coastguard Worker     cupsd_subscription_t *second,	/* I - Second subscription object */
1201*5e7646d2SAndroid Build Coastguard Worker     void		 *unused)	/* I - Unused user data pointer */
1202*5e7646d2SAndroid Build Coastguard Worker {
1203*5e7646d2SAndroid Build Coastguard Worker   (void)unused;
1204*5e7646d2SAndroid Build Coastguard Worker 
1205*5e7646d2SAndroid Build Coastguard Worker   return (first->id - second->id);
1206*5e7646d2SAndroid Build Coastguard Worker }
1207*5e7646d2SAndroid Build Coastguard Worker 
1208*5e7646d2SAndroid Build Coastguard Worker 
1209*5e7646d2SAndroid Build Coastguard Worker /*
1210*5e7646d2SAndroid Build Coastguard Worker  * 'cupsd_delete_event()' - Delete a single event...
1211*5e7646d2SAndroid Build Coastguard Worker  *
1212*5e7646d2SAndroid Build Coastguard Worker  * Oldest events must be deleted first, otherwise the subscription cache
1213*5e7646d2SAndroid Build Coastguard Worker  * flushing code will not work properly.
1214*5e7646d2SAndroid Build Coastguard Worker  */
1215*5e7646d2SAndroid Build Coastguard Worker 
1216*5e7646d2SAndroid Build Coastguard Worker static void
cupsd_delete_event(cupsd_event_t * event)1217*5e7646d2SAndroid Build Coastguard Worker cupsd_delete_event(cupsd_event_t *event)/* I - Event to delete */
1218*5e7646d2SAndroid Build Coastguard Worker {
1219*5e7646d2SAndroid Build Coastguard Worker  /*
1220*5e7646d2SAndroid Build Coastguard Worker   * Free memory...
1221*5e7646d2SAndroid Build Coastguard Worker   */
1222*5e7646d2SAndroid Build Coastguard Worker 
1223*5e7646d2SAndroid Build Coastguard Worker   ippDelete(event->attrs);
1224*5e7646d2SAndroid Build Coastguard Worker   free(event);
1225*5e7646d2SAndroid Build Coastguard Worker }
1226*5e7646d2SAndroid Build Coastguard Worker 
1227*5e7646d2SAndroid Build Coastguard Worker 
1228*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DBUS
1229*5e7646d2SAndroid Build Coastguard Worker /*
1230*5e7646d2SAndroid Build Coastguard Worker  * 'cupsd_send_dbus()' - Send a DBUS notification...
1231*5e7646d2SAndroid Build Coastguard Worker  */
1232*5e7646d2SAndroid Build Coastguard Worker 
1233*5e7646d2SAndroid Build Coastguard Worker static void
cupsd_send_dbus(cupsd_eventmask_t event,cupsd_printer_t * dest,cupsd_job_t * job)1234*5e7646d2SAndroid Build Coastguard Worker cupsd_send_dbus(cupsd_eventmask_t event,/* I - Event to send */
1235*5e7646d2SAndroid Build Coastguard Worker 		cupsd_printer_t	  *dest,/* I - Destination, if any */
1236*5e7646d2SAndroid Build Coastguard Worker 		cupsd_job_t	  *job) /* I - Job, if any */
1237*5e7646d2SAndroid Build Coastguard Worker {
1238*5e7646d2SAndroid Build Coastguard Worker   DBusError		error;		/* Error, if any */
1239*5e7646d2SAndroid Build Coastguard Worker   DBusMessage		*message;	/* Message to send */
1240*5e7646d2SAndroid Build Coastguard Worker   DBusMessageIter	iter;		/* Iterator for message data */
1241*5e7646d2SAndroid Build Coastguard Worker   const char		*what;		/* What to send */
1242*5e7646d2SAndroid Build Coastguard Worker   static DBusConnection *con = NULL;	/* Connection to DBUS server */
1243*5e7646d2SAndroid Build Coastguard Worker 
1244*5e7646d2SAndroid Build Coastguard Worker 
1245*5e7646d2SAndroid Build Coastguard Worker  /*
1246*5e7646d2SAndroid Build Coastguard Worker   * Figure out what to send, if anything...
1247*5e7646d2SAndroid Build Coastguard Worker   */
1248*5e7646d2SAndroid Build Coastguard Worker 
1249*5e7646d2SAndroid Build Coastguard Worker   if (event & CUPSD_EVENT_PRINTER_ADDED)
1250*5e7646d2SAndroid Build Coastguard Worker     what = "PrinterAdded";
1251*5e7646d2SAndroid Build Coastguard Worker   else if (event & CUPSD_EVENT_PRINTER_DELETED)
1252*5e7646d2SAndroid Build Coastguard Worker     what = "PrinterRemoved";
1253*5e7646d2SAndroid Build Coastguard Worker   else if (event & CUPSD_EVENT_PRINTER_CHANGED)
1254*5e7646d2SAndroid Build Coastguard Worker     what = "QueueChanged";
1255*5e7646d2SAndroid Build Coastguard Worker   else if (event & CUPSD_EVENT_JOB_CREATED)
1256*5e7646d2SAndroid Build Coastguard Worker     what = "JobQueuedLocal";
1257*5e7646d2SAndroid Build Coastguard Worker   else if ((event & CUPSD_EVENT_JOB_STATE) && job &&
1258*5e7646d2SAndroid Build Coastguard Worker 	   job->state_value == IPP_JOB_PROCESSING)
1259*5e7646d2SAndroid Build Coastguard Worker     what = "JobStartedLocal";
1260*5e7646d2SAndroid Build Coastguard Worker   else
1261*5e7646d2SAndroid Build Coastguard Worker     return;
1262*5e7646d2SAndroid Build Coastguard Worker 
1263*5e7646d2SAndroid Build Coastguard Worker  /*
1264*5e7646d2SAndroid Build Coastguard Worker   * Verify connection to DBUS server...
1265*5e7646d2SAndroid Build Coastguard Worker   */
1266*5e7646d2SAndroid Build Coastguard Worker 
1267*5e7646d2SAndroid Build Coastguard Worker   if (con && !dbus_connection_get_is_connected(con))
1268*5e7646d2SAndroid Build Coastguard Worker   {
1269*5e7646d2SAndroid Build Coastguard Worker     dbus_connection_unref(con);
1270*5e7646d2SAndroid Build Coastguard Worker     con = NULL;
1271*5e7646d2SAndroid Build Coastguard Worker   }
1272*5e7646d2SAndroid Build Coastguard Worker 
1273*5e7646d2SAndroid Build Coastguard Worker   if (!con)
1274*5e7646d2SAndroid Build Coastguard Worker   {
1275*5e7646d2SAndroid Build Coastguard Worker     dbus_error_init(&error);
1276*5e7646d2SAndroid Build Coastguard Worker 
1277*5e7646d2SAndroid Build Coastguard Worker     con = dbus_bus_get(getuid() ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, &error);
1278*5e7646d2SAndroid Build Coastguard Worker     if (!con)
1279*5e7646d2SAndroid Build Coastguard Worker     {
1280*5e7646d2SAndroid Build Coastguard Worker       dbus_error_free(&error);
1281*5e7646d2SAndroid Build Coastguard Worker       return;
1282*5e7646d2SAndroid Build Coastguard Worker     }
1283*5e7646d2SAndroid Build Coastguard Worker   }
1284*5e7646d2SAndroid Build Coastguard Worker 
1285*5e7646d2SAndroid Build Coastguard Worker  /*
1286*5e7646d2SAndroid Build Coastguard Worker   * Create and send the new message...
1287*5e7646d2SAndroid Build Coastguard Worker   */
1288*5e7646d2SAndroid Build Coastguard Worker 
1289*5e7646d2SAndroid Build Coastguard Worker   message = dbus_message_new_signal("/com/redhat/PrinterSpooler",
1290*5e7646d2SAndroid Build Coastguard Worker 				    "com.redhat.PrinterSpooler", what);
1291*5e7646d2SAndroid Build Coastguard Worker 
1292*5e7646d2SAndroid Build Coastguard Worker   dbus_message_append_iter_init(message, &iter);
1293*5e7646d2SAndroid Build Coastguard Worker   if (dest)
1294*5e7646d2SAndroid Build Coastguard Worker     dbus_message_iter_append_string(&iter, dest->name);
1295*5e7646d2SAndroid Build Coastguard Worker   if (job)
1296*5e7646d2SAndroid Build Coastguard Worker   {
1297*5e7646d2SAndroid Build Coastguard Worker     dbus_message_iter_append_uint32(&iter, job->id);
1298*5e7646d2SAndroid Build Coastguard Worker     dbus_message_iter_append_string(&iter, job->username);
1299*5e7646d2SAndroid Build Coastguard Worker   }
1300*5e7646d2SAndroid Build Coastguard Worker 
1301*5e7646d2SAndroid Build Coastguard Worker   dbus_connection_send(con, message, NULL);
1302*5e7646d2SAndroid Build Coastguard Worker   dbus_connection_flush(con);
1303*5e7646d2SAndroid Build Coastguard Worker   dbus_message_unref(message);
1304*5e7646d2SAndroid Build Coastguard Worker }
1305*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DBUS */
1306*5e7646d2SAndroid Build Coastguard Worker 
1307*5e7646d2SAndroid Build Coastguard Worker 
1308*5e7646d2SAndroid Build Coastguard Worker /*
1309*5e7646d2SAndroid Build Coastguard Worker  * 'cupsd_send_notification()' - Send a notification for the specified event.
1310*5e7646d2SAndroid Build Coastguard Worker  */
1311*5e7646d2SAndroid Build Coastguard Worker 
1312*5e7646d2SAndroid Build Coastguard Worker static void
cupsd_send_notification(cupsd_subscription_t * sub,cupsd_event_t * event)1313*5e7646d2SAndroid Build Coastguard Worker cupsd_send_notification(
1314*5e7646d2SAndroid Build Coastguard Worker     cupsd_subscription_t *sub,		/* I - Subscription object */
1315*5e7646d2SAndroid Build Coastguard Worker     cupsd_event_t	 *event)	/* I - Event to send */
1316*5e7646d2SAndroid Build Coastguard Worker {
1317*5e7646d2SAndroid Build Coastguard Worker   ipp_state_t	state;			/* IPP event state */
1318*5e7646d2SAndroid Build Coastguard Worker 
1319*5e7646d2SAndroid Build Coastguard Worker 
1320*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG2,
1321*5e7646d2SAndroid Build Coastguard Worker 		  "cupsd_send_notification(sub=%p(%d), event=%p(%s))",
1322*5e7646d2SAndroid Build Coastguard Worker 		  sub, sub->id, event, cupsdEventName(event->event));
1323*5e7646d2SAndroid Build Coastguard Worker 
1324*5e7646d2SAndroid Build Coastguard Worker  /*
1325*5e7646d2SAndroid Build Coastguard Worker   * Allocate the events array as needed...
1326*5e7646d2SAndroid Build Coastguard Worker   */
1327*5e7646d2SAndroid Build Coastguard Worker 
1328*5e7646d2SAndroid Build Coastguard Worker   if (!sub->events)
1329*5e7646d2SAndroid Build Coastguard Worker   {
1330*5e7646d2SAndroid Build Coastguard Worker     sub->events = cupsArrayNew3((cups_array_func_t)NULL, NULL,
1331*5e7646d2SAndroid Build Coastguard Worker 				(cups_ahash_func_t)NULL, 0,
1332*5e7646d2SAndroid Build Coastguard Worker 				(cups_acopy_func_t)NULL,
1333*5e7646d2SAndroid Build Coastguard Worker 				(cups_afree_func_t)cupsd_delete_event);
1334*5e7646d2SAndroid Build Coastguard Worker 
1335*5e7646d2SAndroid Build Coastguard Worker     if (!sub->events)
1336*5e7646d2SAndroid Build Coastguard Worker     {
1337*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_CRIT,
1338*5e7646d2SAndroid Build Coastguard Worker 		      "Unable to allocate memory for subscription #%d!",
1339*5e7646d2SAndroid Build Coastguard Worker 		      sub->id);
1340*5e7646d2SAndroid Build Coastguard Worker       return;
1341*5e7646d2SAndroid Build Coastguard Worker     }
1342*5e7646d2SAndroid Build Coastguard Worker   }
1343*5e7646d2SAndroid Build Coastguard Worker 
1344*5e7646d2SAndroid Build Coastguard Worker  /*
1345*5e7646d2SAndroid Build Coastguard Worker   * Purge an old event as needed...
1346*5e7646d2SAndroid Build Coastguard Worker   */
1347*5e7646d2SAndroid Build Coastguard Worker 
1348*5e7646d2SAndroid Build Coastguard Worker   if (cupsArrayCount(sub->events) >= MaxEvents)
1349*5e7646d2SAndroid Build Coastguard Worker   {
1350*5e7646d2SAndroid Build Coastguard Worker    /*
1351*5e7646d2SAndroid Build Coastguard Worker     * Purge the oldest event in the cache...
1352*5e7646d2SAndroid Build Coastguard Worker     */
1353*5e7646d2SAndroid Build Coastguard Worker 
1354*5e7646d2SAndroid Build Coastguard Worker     cupsArrayRemove(sub->events, cupsArrayFirst(sub->events));
1355*5e7646d2SAndroid Build Coastguard Worker 
1356*5e7646d2SAndroid Build Coastguard Worker     sub->first_event_id ++;
1357*5e7646d2SAndroid Build Coastguard Worker   }
1358*5e7646d2SAndroid Build Coastguard Worker 
1359*5e7646d2SAndroid Build Coastguard Worker  /*
1360*5e7646d2SAndroid Build Coastguard Worker   * Add the event to the subscription.	Since the events array is
1361*5e7646d2SAndroid Build Coastguard Worker   * always MaxEvents in length, and since we will have already
1362*5e7646d2SAndroid Build Coastguard Worker   * removed an event from the subscription cache if we hit the
1363*5e7646d2SAndroid Build Coastguard Worker   * event cache limit, we don't need to check for overflow here...
1364*5e7646d2SAndroid Build Coastguard Worker   */
1365*5e7646d2SAndroid Build Coastguard Worker 
1366*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(sub->events, event);
1367*5e7646d2SAndroid Build Coastguard Worker 
1368*5e7646d2SAndroid Build Coastguard Worker  /*
1369*5e7646d2SAndroid Build Coastguard Worker   * Deliver the event...
1370*5e7646d2SAndroid Build Coastguard Worker   */
1371*5e7646d2SAndroid Build Coastguard Worker 
1372*5e7646d2SAndroid Build Coastguard Worker   if (sub->recipient)
1373*5e7646d2SAndroid Build Coastguard Worker   {
1374*5e7646d2SAndroid Build Coastguard Worker     for (;;)
1375*5e7646d2SAndroid Build Coastguard Worker     {
1376*5e7646d2SAndroid Build Coastguard Worker       if (sub->pipe < 0)
1377*5e7646d2SAndroid Build Coastguard Worker 	cupsd_start_notifier(sub);
1378*5e7646d2SAndroid Build Coastguard Worker 
1379*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_DEBUG2, "sub->pipe=%d", sub->pipe);
1380*5e7646d2SAndroid Build Coastguard Worker 
1381*5e7646d2SAndroid Build Coastguard Worker       if (sub->pipe < 0)
1382*5e7646d2SAndroid Build Coastguard Worker 	break;
1383*5e7646d2SAndroid Build Coastguard Worker 
1384*5e7646d2SAndroid Build Coastguard Worker       event->attrs->state = IPP_IDLE;
1385*5e7646d2SAndroid Build Coastguard Worker 
1386*5e7646d2SAndroid Build Coastguard Worker       while ((state = ippWriteFile(sub->pipe, event->attrs)) != IPP_DATA)
1387*5e7646d2SAndroid Build Coastguard Worker 	if (state == IPP_ERROR)
1388*5e7646d2SAndroid Build Coastguard Worker 	  break;
1389*5e7646d2SAndroid Build Coastguard Worker 
1390*5e7646d2SAndroid Build Coastguard Worker       if (state == IPP_ERROR)
1391*5e7646d2SAndroid Build Coastguard Worker       {
1392*5e7646d2SAndroid Build Coastguard Worker 	if (errno == EPIPE)
1393*5e7646d2SAndroid Build Coastguard Worker 	{
1394*5e7646d2SAndroid Build Coastguard Worker 	 /*
1395*5e7646d2SAndroid Build Coastguard Worker 	  * Notifier died, try restarting it...
1396*5e7646d2SAndroid Build Coastguard Worker 	  */
1397*5e7646d2SAndroid Build Coastguard Worker 
1398*5e7646d2SAndroid Build Coastguard Worker 	  cupsdLogMessage(CUPSD_LOG_WARN,
1399*5e7646d2SAndroid Build Coastguard Worker 			  "Notifier for subscription %d (%s) went away, "
1400*5e7646d2SAndroid Build Coastguard Worker 			  "retrying!",
1401*5e7646d2SAndroid Build Coastguard Worker 			  sub->id, sub->recipient);
1402*5e7646d2SAndroid Build Coastguard Worker 	  cupsdEndProcess(sub->pid, 0);
1403*5e7646d2SAndroid Build Coastguard Worker 
1404*5e7646d2SAndroid Build Coastguard Worker 	  close(sub->pipe);
1405*5e7646d2SAndroid Build Coastguard Worker 	  sub->pipe = -1;
1406*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1407*5e7646d2SAndroid Build Coastguard Worker 	}
1408*5e7646d2SAndroid Build Coastguard Worker 
1409*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_ERROR,
1410*5e7646d2SAndroid Build Coastguard Worker 			"Unable to send event for subscription %d (%s)!",
1411*5e7646d2SAndroid Build Coastguard Worker 			sub->id, sub->recipient);
1412*5e7646d2SAndroid Build Coastguard Worker       }
1413*5e7646d2SAndroid Build Coastguard Worker 
1414*5e7646d2SAndroid Build Coastguard Worker      /*
1415*5e7646d2SAndroid Build Coastguard Worker       * If we get this far, break out of the loop...
1416*5e7646d2SAndroid Build Coastguard Worker       */
1417*5e7646d2SAndroid Build Coastguard Worker 
1418*5e7646d2SAndroid Build Coastguard Worker       break;
1419*5e7646d2SAndroid Build Coastguard Worker     }
1420*5e7646d2SAndroid Build Coastguard Worker   }
1421*5e7646d2SAndroid Build Coastguard Worker 
1422*5e7646d2SAndroid Build Coastguard Worker  /*
1423*5e7646d2SAndroid Build Coastguard Worker   * Bump the event sequence number...
1424*5e7646d2SAndroid Build Coastguard Worker   */
1425*5e7646d2SAndroid Build Coastguard Worker 
1426*5e7646d2SAndroid Build Coastguard Worker   sub->next_event_id ++;
1427*5e7646d2SAndroid Build Coastguard Worker }
1428*5e7646d2SAndroid Build Coastguard Worker 
1429*5e7646d2SAndroid Build Coastguard Worker 
1430*5e7646d2SAndroid Build Coastguard Worker /*
1431*5e7646d2SAndroid Build Coastguard Worker  * 'cupsd_start_notifier()' - Start a notifier subprocess...
1432*5e7646d2SAndroid Build Coastguard Worker  */
1433*5e7646d2SAndroid Build Coastguard Worker 
1434*5e7646d2SAndroid Build Coastguard Worker static void
cupsd_start_notifier(cupsd_subscription_t * sub)1435*5e7646d2SAndroid Build Coastguard Worker cupsd_start_notifier(
1436*5e7646d2SAndroid Build Coastguard Worker     cupsd_subscription_t *sub)		/* I - Subscription object */
1437*5e7646d2SAndroid Build Coastguard Worker {
1438*5e7646d2SAndroid Build Coastguard Worker   int	pid;				/* Notifier process ID */
1439*5e7646d2SAndroid Build Coastguard Worker   int	fds[2];				/* Pipe file descriptors */
1440*5e7646d2SAndroid Build Coastguard Worker   char	*argv[4],			/* Command-line arguments */
1441*5e7646d2SAndroid Build Coastguard Worker 	*envp[MAX_ENV],			/* Environment variables */
1442*5e7646d2SAndroid Build Coastguard Worker 	user_data[128],			/* Base-64 encoded user data */
1443*5e7646d2SAndroid Build Coastguard Worker 	scheme[256],			/* notify-recipient-uri scheme */
1444*5e7646d2SAndroid Build Coastguard Worker 	*ptr,				/* Pointer into scheme */
1445*5e7646d2SAndroid Build Coastguard Worker 	command[1024];			/* Notifier command */
1446*5e7646d2SAndroid Build Coastguard Worker 
1447*5e7646d2SAndroid Build Coastguard Worker 
1448*5e7646d2SAndroid Build Coastguard Worker  /*
1449*5e7646d2SAndroid Build Coastguard Worker   * Extract the scheme name from the recipient URI and point to the
1450*5e7646d2SAndroid Build Coastguard Worker   * notifier program...
1451*5e7646d2SAndroid Build Coastguard Worker   */
1452*5e7646d2SAndroid Build Coastguard Worker 
1453*5e7646d2SAndroid Build Coastguard Worker   strlcpy(scheme, sub->recipient, sizeof(scheme));
1454*5e7646d2SAndroid Build Coastguard Worker   if ((ptr = strchr(scheme, ':')) != NULL)
1455*5e7646d2SAndroid Build Coastguard Worker     *ptr = '\0';
1456*5e7646d2SAndroid Build Coastguard Worker 
1457*5e7646d2SAndroid Build Coastguard Worker   snprintf(command, sizeof(command), "%s/notifier/%s", ServerBin, scheme);
1458*5e7646d2SAndroid Build Coastguard Worker 
1459*5e7646d2SAndroid Build Coastguard Worker  /*
1460*5e7646d2SAndroid Build Coastguard Worker   * Base-64 encode the user data...
1461*5e7646d2SAndroid Build Coastguard Worker   */
1462*5e7646d2SAndroid Build Coastguard Worker 
1463*5e7646d2SAndroid Build Coastguard Worker   httpEncode64_2(user_data, sizeof(user_data), (char *)sub->user_data,
1464*5e7646d2SAndroid Build Coastguard Worker 		 sub->user_data_len);
1465*5e7646d2SAndroid Build Coastguard Worker 
1466*5e7646d2SAndroid Build Coastguard Worker  /*
1467*5e7646d2SAndroid Build Coastguard Worker   * Setup the argument array...
1468*5e7646d2SAndroid Build Coastguard Worker   */
1469*5e7646d2SAndroid Build Coastguard Worker 
1470*5e7646d2SAndroid Build Coastguard Worker   argv[0] = command;
1471*5e7646d2SAndroid Build Coastguard Worker   argv[1] = sub->recipient;
1472*5e7646d2SAndroid Build Coastguard Worker   argv[2] = user_data;
1473*5e7646d2SAndroid Build Coastguard Worker   argv[3] = NULL;
1474*5e7646d2SAndroid Build Coastguard Worker 
1475*5e7646d2SAndroid Build Coastguard Worker  /*
1476*5e7646d2SAndroid Build Coastguard Worker   * Setup the environment...
1477*5e7646d2SAndroid Build Coastguard Worker   */
1478*5e7646d2SAndroid Build Coastguard Worker 
1479*5e7646d2SAndroid Build Coastguard Worker   cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
1480*5e7646d2SAndroid Build Coastguard Worker 
1481*5e7646d2SAndroid Build Coastguard Worker  /*
1482*5e7646d2SAndroid Build Coastguard Worker   * Create pipes as needed...
1483*5e7646d2SAndroid Build Coastguard Worker   */
1484*5e7646d2SAndroid Build Coastguard Worker 
1485*5e7646d2SAndroid Build Coastguard Worker   if (!NotifierStatusBuffer)
1486*5e7646d2SAndroid Build Coastguard Worker   {
1487*5e7646d2SAndroid Build Coastguard Worker    /*
1488*5e7646d2SAndroid Build Coastguard Worker     * Create the status pipe...
1489*5e7646d2SAndroid Build Coastguard Worker     */
1490*5e7646d2SAndroid Build Coastguard Worker 
1491*5e7646d2SAndroid Build Coastguard Worker     if (cupsdOpenPipe(NotifierPipes))
1492*5e7646d2SAndroid Build Coastguard Worker     {
1493*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_ERROR,
1494*5e7646d2SAndroid Build Coastguard Worker 		      "Unable to create pipes for notifier status - %s",
1495*5e7646d2SAndroid Build Coastguard Worker 		      strerror(errno));
1496*5e7646d2SAndroid Build Coastguard Worker       return;
1497*5e7646d2SAndroid Build Coastguard Worker     }
1498*5e7646d2SAndroid Build Coastguard Worker 
1499*5e7646d2SAndroid Build Coastguard Worker     NotifierStatusBuffer = cupsdStatBufNew(NotifierPipes[0], "[Notifier]");
1500*5e7646d2SAndroid Build Coastguard Worker 
1501*5e7646d2SAndroid Build Coastguard Worker     cupsdAddSelect(NotifierPipes[0], (cupsd_selfunc_t)cupsd_update_notifier,
1502*5e7646d2SAndroid Build Coastguard Worker 		   NULL, NULL);
1503*5e7646d2SAndroid Build Coastguard Worker   }
1504*5e7646d2SAndroid Build Coastguard Worker 
1505*5e7646d2SAndroid Build Coastguard Worker   if (cupsdOpenPipe(fds))
1506*5e7646d2SAndroid Build Coastguard Worker   {
1507*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_ERROR,
1508*5e7646d2SAndroid Build Coastguard Worker 		    "Unable to create pipes for notifier %s - %s",
1509*5e7646d2SAndroid Build Coastguard Worker 		    scheme, strerror(errno));
1510*5e7646d2SAndroid Build Coastguard Worker     return;
1511*5e7646d2SAndroid Build Coastguard Worker   }
1512*5e7646d2SAndroid Build Coastguard Worker 
1513*5e7646d2SAndroid Build Coastguard Worker  /*
1514*5e7646d2SAndroid Build Coastguard Worker   * Make sure the delivery pipe is non-blocking...
1515*5e7646d2SAndroid Build Coastguard Worker   */
1516*5e7646d2SAndroid Build Coastguard Worker 
1517*5e7646d2SAndroid Build Coastguard Worker   fcntl(fds[1], F_SETFL, fcntl(fds[1], F_GETFL) | O_NONBLOCK);
1518*5e7646d2SAndroid Build Coastguard Worker 
1519*5e7646d2SAndroid Build Coastguard Worker  /*
1520*5e7646d2SAndroid Build Coastguard Worker   * Create the notifier process...
1521*5e7646d2SAndroid Build Coastguard Worker   */
1522*5e7646d2SAndroid Build Coastguard Worker 
1523*5e7646d2SAndroid Build Coastguard Worker   if (cupsdStartProcess(command, argv, envp, fds[0], -1, NotifierPipes[1],
1524*5e7646d2SAndroid Build Coastguard Worker 			-1, -1, 0, DefaultProfile, NULL, &pid) < 0)
1525*5e7646d2SAndroid Build Coastguard Worker   {
1526*5e7646d2SAndroid Build Coastguard Worker    /*
1527*5e7646d2SAndroid Build Coastguard Worker     * Error - can't fork!
1528*5e7646d2SAndroid Build Coastguard Worker     */
1529*5e7646d2SAndroid Build Coastguard Worker 
1530*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork for notifier %s - %s",
1531*5e7646d2SAndroid Build Coastguard Worker 		    scheme, strerror(errno));
1532*5e7646d2SAndroid Build Coastguard Worker 
1533*5e7646d2SAndroid Build Coastguard Worker     cupsdClosePipe(fds);
1534*5e7646d2SAndroid Build Coastguard Worker   }
1535*5e7646d2SAndroid Build Coastguard Worker   else
1536*5e7646d2SAndroid Build Coastguard Worker   {
1537*5e7646d2SAndroid Build Coastguard Worker    /*
1538*5e7646d2SAndroid Build Coastguard Worker     * Fork successful - return the PID...
1539*5e7646d2SAndroid Build Coastguard Worker     */
1540*5e7646d2SAndroid Build Coastguard Worker 
1541*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_DEBUG, "Notifier %s started - PID = %d",
1542*5e7646d2SAndroid Build Coastguard Worker 		    scheme, pid);
1543*5e7646d2SAndroid Build Coastguard Worker 
1544*5e7646d2SAndroid Build Coastguard Worker     sub->pid	= pid;
1545*5e7646d2SAndroid Build Coastguard Worker     sub->pipe	= fds[1];
1546*5e7646d2SAndroid Build Coastguard Worker     sub->status = 0;
1547*5e7646d2SAndroid Build Coastguard Worker 
1548*5e7646d2SAndroid Build Coastguard Worker     close(fds[0]);
1549*5e7646d2SAndroid Build Coastguard Worker   }
1550*5e7646d2SAndroid Build Coastguard Worker }
1551*5e7646d2SAndroid Build Coastguard Worker 
1552*5e7646d2SAndroid Build Coastguard Worker 
1553*5e7646d2SAndroid Build Coastguard Worker /*
1554*5e7646d2SAndroid Build Coastguard Worker  * 'cupsd_update_notifier()' - Read messages from notifiers.
1555*5e7646d2SAndroid Build Coastguard Worker  */
1556*5e7646d2SAndroid Build Coastguard Worker 
1557*5e7646d2SAndroid Build Coastguard Worker void
cupsd_update_notifier(void)1558*5e7646d2SAndroid Build Coastguard Worker cupsd_update_notifier(void)
1559*5e7646d2SAndroid Build Coastguard Worker {
1560*5e7646d2SAndroid Build Coastguard Worker   char		message[1024];		/* Pointer to message text */
1561*5e7646d2SAndroid Build Coastguard Worker   int		loglevel;		/* Log level for message */
1562*5e7646d2SAndroid Build Coastguard Worker 
1563*5e7646d2SAndroid Build Coastguard Worker 
1564*5e7646d2SAndroid Build Coastguard Worker   while (cupsdStatBufUpdate(NotifierStatusBuffer, &loglevel,
1565*5e7646d2SAndroid Build Coastguard Worker 			    message, sizeof(message)))
1566*5e7646d2SAndroid Build Coastguard Worker   {
1567*5e7646d2SAndroid Build Coastguard Worker     if (loglevel == CUPSD_LOG_INFO)
1568*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_INFO, "%s", message);
1569*5e7646d2SAndroid Build Coastguard Worker 
1570*5e7646d2SAndroid Build Coastguard Worker     if (!strchr(NotifierStatusBuffer->buffer, '\n'))
1571*5e7646d2SAndroid Build Coastguard Worker       break;
1572*5e7646d2SAndroid Build Coastguard Worker   }
1573*5e7646d2SAndroid Build Coastguard Worker }
1574