]>
git.ipfire.org Git - thirdparty/cups.git/blob - notifier/dbus.c
2 * D-Bus notifier for CUPS.
4 * Copyright 2008-2014 by Apple Inc.
5 * Copyright (C) 2011, 2013 Red Hat, Inc.
6 * Copyright (C) 2007 Tim Waugh <twaugh@redhat.com>
7 * Copyright 1997-2005 by Easy Software Products.
9 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
13 * Include necessary headers...
16 #include <cups/cups.h>
17 #include <cups/string-private.h>
21 #include <sys/types.h>
25 # include <dbus/dbus.h>
26 # ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND
27 # define dbus_message_append_iter_init dbus_message_iter_init_append
28 # define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, v)
29 # define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, v)
30 # define dbus_message_iter_append_boolean(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, v)
31 # endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
35 * D-Bus object: org.cups.cupsd.Notifier
36 * D-Bus object path: /org/cups/cupsd/Notifier
38 * D-Bus interface name: org.cups.cupsd.Notifier
42 * ServerRestarted(STRING text)
43 * Server has restarted.
45 * ServerStarted(STRING text)
48 * ServerStopped(STRING text)
51 * ServerAudit(STRING text)
52 * Security-related event.
54 * PrinterRestarted(STRING text,
56 * STRING printer-name,
57 * UINT32 printer-state,
58 * STRING printer-state-reasons,
59 * BOOLEAN printer-is-accepting-jobs)
60 * Printer has restarted.
62 * PrinterShutdown(STRING text,
64 * STRING printer-name,
65 * UINT32 printer-state,
66 * STRING printer-state-reasons,
67 * BOOLEAN printer-is-accepting-jobs)
68 * Printer has shutdown.
70 * PrinterStopped(STRING text,
72 * STRING printer-name,
73 * UINT32 printer-state,
74 * STRING printer-state-reasons,
75 * BOOLEAN printer-is-accepting-jobs)
76 * Printer has stopped.
78 * PrinterStateChanged(STRING text,
80 * STRING printer-name,
81 * UINT32 printer-state,
82 * STRING printer-state-reasons,
83 * BOOLEAN printer-is-accepting-jobs)
84 * Printer state has changed.
86 * PrinterFinishingsChanged(STRING text,
88 * STRING printer-name,
89 * UINT32 printer-state,
90 * STRING printer-state-reasons,
91 * BOOLEAN printer-is-accepting-jobs)
92 * Printer's finishings-supported attribute has changed.
94 * PrinterMediaChanged(STRING text,
96 * STRING printer-name,
97 * UINT32 printer-state,
98 * STRING printer-state-reasons,
99 * BOOLEAN printer-is-accepting-jobs)
100 * Printer's media-supported attribute has changed.
102 * PrinterAdded(STRING text,
103 * STRING printer-uri,
104 * STRING printer-name,
105 * UINT32 printer-state,
106 * STRING printer-state-reasons,
107 * BOOLEAN printer-is-accepting-jobs)
108 * Printer has been added.
110 * PrinterDeleted(STRING text,
111 * STRING printer-uri,
112 * STRING printer-name,
113 * UINT32 printer-state,
114 * STRING printer-state-reasons,
115 * BOOLEAN printer-is-accepting-jobs)
116 * Printer has been deleted.
118 * PrinterModified(STRING text,
119 * STRING printer-uri,
120 * STRING printer-name,
121 * UINT32 printer-state,
122 * STRING printer-state-reasons,
123 * BOOLEAN printer-is-accepting-jobs)
124 * Printer has been modified.
126 * text describes the event.
127 * printer-state-reasons is a comma-separated list.
128 * If printer-uri is "" in a Job* signal, the other printer-* parameters
130 * If the job name is not know, job-name will be "".
146 * Global variables...
149 static char lock_filename
[1024]; /* Lock filename */
156 static int acquire_lock(int *fd
, char *lockfile
, size_t locksize
);
157 static void release_lock(void);
161 * 'main()' - Read events and send DBUS notifications.
164 int /* O - Exit status */
165 main(int argc
, /* I - Number of command-line args */
166 char *argv
[]) /* I - Command-line arguments */
168 ipp_t
*msg
; /* Event message from scheduler */
169 ipp_state_t state
; /* IPP event state */
170 struct sigaction action
; /* POSIX sigaction data */
171 DBusConnection
*con
= NULL
; /* Connection to DBUS server */
172 DBusError error
; /* Error, if any */
173 DBusMessage
*message
; /* Message to send */
174 DBusMessageIter iter
; /* Iterator for message data */
175 int lock_fd
= -1; /* Lock file descriptor */
179 * Don't buffer stderr...
182 setbuf(stderr
, NULL
);
185 * Ignore SIGPIPE signals...
188 memset(&action
, 0, sizeof(action
));
189 action
.sa_handler
= SIG_IGN
;
190 sigaction(SIGPIPE
, &action
, NULL
);
193 * Validate command-line options...
198 fputs("Usage: dbus dbus:/// notify-user-data\n", stderr
);
202 if (strncmp(argv
[1], "dbus:", 5))
204 fprintf(stderr
, "ERROR: Bad URI \"%s\"!\n", argv
[1]);
209 * Loop forever until we run out of events...
214 ipp_attribute_t
*attr
; /* Current attribute */
215 const char *event
; /* Event name */
216 const char *signame
= NULL
;/* DBUS signal name */
217 char *printer_reasons
= NULL
;
218 /* Printer reasons string */
219 char *job_reasons
= NULL
;
220 /* Job reasons string */
221 const char *nul
= ""; /* Empty string value */
222 int no
= 0; /* Boolean "no" value */
223 int params
= PARAMS_NONE
;
224 /* What parameters to include? */
228 * Get the next event...
232 while ((state
= ippReadFile(0, msg
)) != IPP_DATA
)
234 if (state
<= IPP_IDLE
)
238 fprintf(stderr
, "DEBUG: state=%d\n", state
);
240 if (state
== IPP_ERROR
)
241 fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr
);
243 if (state
<= IPP_IDLE
)
246 * Out of messages, free memory and then exit...
254 * Verify connection to DBUS server...
257 if (con
&& !dbus_connection_get_is_connected(con
))
259 dbus_connection_unref(con
);
265 dbus_error_init(&error
);
267 con
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
);
269 dbus_error_free(&error
);
271 fputs("DEBUG: Connected to D-BUS\n", stderr
);
278 acquire_lock(&lock_fd
, lock_filename
, sizeof(lock_filename
)))
281 attr
= ippFindAttribute(msg
, "notify-subscribed-event",
286 event
= ippGetString(attr
, 0, NULL
);
287 if (!strncmp(event
, "server-", 7))
289 const char *word2
= event
+ 7; /* Second word */
291 if (!strcmp(word2
, "restarted"))
292 signame
= "ServerRestarted";
293 else if (!strcmp(word2
, "started"))
294 signame
= "ServerStarted";
295 else if (!strcmp(word2
, "stopped"))
296 signame
= "ServerStopped";
297 else if (!strcmp(word2
, "audit"))
298 signame
= "ServerAudit";
302 else if (!strncmp(event
, "printer-", 8))
304 const char *word2
= event
+ 8; /* Second word */
306 params
= PARAMS_PRINTER
;
307 if (!strcmp(word2
, "restarted"))
308 signame
= "PrinterRestarted";
309 else if (!strcmp(word2
, "shutdown"))
310 signame
= "PrinterShutdown";
311 else if (!strcmp(word2
, "stopped"))
312 signame
= "PrinterStopped";
313 else if (!strcmp(word2
, "state-changed"))
314 signame
= "PrinterStateChanged";
315 else if (!strcmp(word2
, "finishings-changed"))
316 signame
= "PrinterFinishingsChanged";
317 else if (!strcmp(word2
, "media-changed"))
318 signame
= "PrinterMediaChanged";
319 else if (!strcmp(word2
, "added"))
320 signame
= "PrinterAdded";
321 else if (!strcmp(word2
, "deleted"))
322 signame
= "PrinterDeleted";
323 else if (!strcmp(word2
, "modified"))
324 signame
= "PrinterModified";
328 else if (!strncmp(event
, "job-", 4))
330 const char *word2
= event
+ 4; /* Second word */
333 if (!strcmp(word2
, "state-changed"))
334 signame
= "JobState";
335 else if (!strcmp(word2
, "created"))
336 signame
= "JobCreated";
337 else if (!strcmp(word2
, "completed"))
338 signame
= "JobCompleted";
339 else if (!strcmp(word2
, "stopped"))
340 signame
= "JobStopped";
341 else if (!strcmp(word2
, "config-changed"))
342 signame
= "JobConfigChanged";
343 else if (!strcmp(word2
, "progress"))
344 signame
= "JobProgress";
352 * Create and send the new message...
355 fprintf(stderr
, "DEBUG: %s\n", signame
);
356 message
= dbus_message_new_signal("/org/cups/cupsd/Notifier",
357 "org.cups.cupsd.Notifier",
360 dbus_message_append_iter_init(message
, &iter
);
361 attr
= ippFindAttribute(msg
, "notify-text", IPP_TAG_TEXT
);
364 const char *val
= ippGetString(attr
, 0, NULL
);
365 if (!dbus_message_iter_append_string(&iter
, &val
))
371 if (params
>= PARAMS_PRINTER
)
373 char *p
; /* Pointer into printer_reasons */
374 size_t reasons_length
; /* Required size of printer_reasons */
375 int i
; /* Looping var */
376 int have_printer_params
= 1;/* Do we have printer URI? */
378 /* STRING printer-uri or "" */
379 attr
= ippFindAttribute(msg
, "notify-printer-uri", IPP_TAG_URI
);
382 const char *val
= ippGetString(attr
, 0, NULL
);
383 if (!dbus_message_iter_append_string(&iter
, &val
))
388 have_printer_params
= 0;
389 dbus_message_iter_append_string(&iter
, &nul
);
392 /* STRING printer-name */
393 if (have_printer_params
)
395 attr
= ippFindAttribute(msg
, "printer-name", IPP_TAG_NAME
);
398 const char *val
= ippGetString(attr
, 0, NULL
);
399 if (!dbus_message_iter_append_string(&iter
, &val
))
406 dbus_message_iter_append_string(&iter
, &nul
);
408 /* UINT32 printer-state */
409 if (have_printer_params
)
411 attr
= ippFindAttribute(msg
, "printer-state", IPP_TAG_ENUM
);
414 dbus_uint32_t val
= (dbus_uint32_t
)ippGetInteger(attr
, 0);
415 dbus_message_iter_append_uint32(&iter
, &val
);
421 dbus_message_iter_append_uint32(&iter
, &no
);
423 /* STRING printer-state-reasons */
424 if (have_printer_params
)
426 attr
= ippFindAttribute(msg
, "printer-state-reasons",
430 int num_values
= ippGetCount(attr
);
431 for (reasons_length
= 0, i
= 0; i
< num_values
; i
++)
432 /* All need commas except the last, which needs a nul byte. */
433 reasons_length
+= 1 + strlen(ippGetString(attr
, i
, NULL
));
434 printer_reasons
= malloc(reasons_length
);
435 if (!printer_reasons
)
438 for (i
= 0; i
< num_values
; i
++)
443 strlcpy(p
, ippGetString(attr
, i
, NULL
), reasons_length
- (size_t)(p
- printer_reasons
));
446 if (!dbus_message_iter_append_string(&iter
, &printer_reasons
))
453 dbus_message_iter_append_string(&iter
, &nul
);
455 /* BOOL printer-is-accepting-jobs */
456 if (have_printer_params
)
458 attr
= ippFindAttribute(msg
, "printer-is-accepting-jobs",
462 dbus_bool_t val
= (dbus_bool_t
)ippGetBoolean(attr
, 0);
463 dbus_message_iter_append_boolean(&iter
, &val
);
469 dbus_message_iter_append_boolean(&iter
, &no
);
472 if (params
>= PARAMS_JOB
)
474 char *p
; /* Pointer into job_reasons */
475 size_t reasons_length
; /* Required size of job_reasons */
476 int i
; /* Looping var */
479 attr
= ippFindAttribute(msg
, "notify-job-id", IPP_TAG_INTEGER
);
482 dbus_uint32_t val
= (dbus_uint32_t
)ippGetInteger(attr
, 0);
483 dbus_message_iter_append_uint32(&iter
, &val
);
488 /* UINT32 job-state */
489 attr
= ippFindAttribute(msg
, "job-state", IPP_TAG_ENUM
);
492 dbus_uint32_t val
= (dbus_uint32_t
)ippGetInteger(attr
, 0);
493 dbus_message_iter_append_uint32(&iter
, &val
);
498 /* STRING job-state-reasons */
499 attr
= ippFindAttribute(msg
, "job-state-reasons", IPP_TAG_KEYWORD
);
502 int num_values
= ippGetCount(attr
);
503 for (reasons_length
= 0, i
= 0; i
< num_values
; i
++)
504 /* All need commas except the last, which needs a nul byte. */
505 reasons_length
+= 1 + strlen(ippGetString(attr
, i
, NULL
));
506 job_reasons
= malloc(reasons_length
);
510 for (i
= 0; i
< num_values
; i
++)
515 strlcpy(p
, ippGetString(attr
, i
, NULL
), reasons_length
- (size_t)(p
- job_reasons
));
518 if (!dbus_message_iter_append_string(&iter
, &job_reasons
))
524 /* STRING job-name or "" */
525 attr
= ippFindAttribute(msg
, "job-name", IPP_TAG_NAME
);
528 const char *val
= ippGetString(attr
, 0, NULL
);
529 if (!dbus_message_iter_append_string(&iter
, &val
))
533 dbus_message_iter_append_string(&iter
, &nul
);
535 /* UINT32 job-impressions-completed */
536 attr
= ippFindAttribute(msg
, "job-impressions-completed",
540 dbus_uint32_t val
= (dbus_uint32_t
)ippGetInteger(attr
, 0);
541 dbus_message_iter_append_uint32(&iter
, &val
);
547 dbus_connection_send(con
, message
, NULL
);
548 dbus_connection_flush(con
);
556 dbus_message_unref(message
);
559 free(printer_reasons
);
568 * Remove lock file...
582 * 'release_lock()' - Release the singleton lock.
588 unlink(lock_filename
);
593 * 'handle_sigterm()' - Handle SIGTERM signal.
596 handle_sigterm(int signum
)
603 * 'acquire_lock()' - Acquire a lock so we only have a single notifier running.
606 static int /* O - 0 on success, -1 on failure */
607 acquire_lock(int *fd
, /* O - Lock file descriptor */
608 char *lockfile
, /* I - Lock filename buffer */
609 size_t locksize
) /* I - Size of filename buffer */
611 const char *tmpdir
; /* Temporary directory */
612 struct sigaction action
; /* POSIX sigaction data */
616 * Figure out where to put the lock file...
619 if ((tmpdir
= getenv("TMPDIR")) == NULL
)
622 snprintf(lockfile
, locksize
, "%s/cups-dbus-notifier-lockfile", tmpdir
);
625 * Create the lock file and fail if it already exists...
628 if ((*fd
= open(lockfile
, O_RDWR
| O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
)) < 0)
632 * Set a SIGTERM handler to make sure we release the lock if the
633 * scheduler decides to stop us.
635 memset(&action
, 0, sizeof(action
));
636 action
.sa_handler
= handle_sigterm
;
637 sigaction(SIGTERM
, &action
, NULL
);
641 #else /* !HAVE_DBUS */
647 #endif /* HAVE_DBUS */