]>
git.ipfire.org Git - thirdparty/cups.git/blob - notifier/dbus.c
1629c4e7fcdc49818a4e9f10cb4293556ced112b
4 * D-Bus notifier for CUPS.
6 * Copyright 2008-2012 by Apple Inc.
7 * Copyright (C) 2011 Red Hat, Inc.
8 * Copyright (C) 2007 Tim Waugh <twaugh@redhat.com>
9 * Copyright 1997-2005 by Easy Software Products.
11 * These coded instructions, statements, and computer programs are the
12 * property of Apple Inc. and are protected by Federal copyright
13 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
14 * which should have been included with this file. If this file is
15 * file is missing or damaged, see the license at "http://www.cups.org/".
19 * main() - Read events and send DBUS notifications.
20 * acquire_lock() - Acquire a lock so we only have a single notifier running.
24 * Include necessary headers...
27 #include <cups/cups.h>
28 #include <cups/string-private.h>
32 #include <sys/types.h>
36 # include <dbus/dbus.h>
37 # ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND
38 # define dbus_message_append_iter_init dbus_message_iter_init_append
39 # define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, v)
40 # define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, v)
41 # define dbus_message_iter_append_boolean(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, v)
42 # endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
46 * D-Bus object: org.cups.cupsd.Notifier
47 * D-Bus object path: /org/cups/cupsd/Notifier
49 * D-Bus interface name: org.cups.cupsd.Notifier
53 * ServerRestarted(STRING text)
54 * Server has restarted.
56 * ServerStarted(STRING text)
59 * ServerStopped(STRING text)
62 * ServerAudit(STRING text)
63 * Security-related event.
65 * PrinterRestarted(STRING text,
67 * STRING printer-name,
68 * UINT32 printer-state,
69 * STRING printer-state-reasons,
70 * BOOLEAN printer-is-accepting-jobs)
71 * Printer has restarted.
73 * PrinterShutdown(STRING text,
75 * STRING printer-name,
76 * UINT32 printer-state,
77 * STRING printer-state-reasons,
78 * BOOLEAN printer-is-accepting-jobs)
79 * Printer has shutdown.
81 * PrinterStopped(STRING text,
83 * STRING printer-name,
84 * UINT32 printer-state,
85 * STRING printer-state-reasons,
86 * BOOLEAN printer-is-accepting-jobs)
87 * Printer has stopped.
89 * PrinterStateChanged(STRING text,
91 * STRING printer-name,
92 * UINT32 printer-state,
93 * STRING printer-state-reasons,
94 * BOOLEAN printer-is-accepting-jobs)
95 * Printer state has changed.
97 * PrinterFinishingsChanged(STRING text,
99 * STRING printer-name,
100 * UINT32 printer-state,
101 * STRING printer-state-reasons,
102 * BOOLEAN printer-is-accepting-jobs)
103 * Printer's finishings-supported attribute has changed.
105 * PrinterMediaChanged(STRING text,
106 * STRING printer-uri,
107 * STRING printer-name,
108 * UINT32 printer-state,
109 * STRING printer-state-reasons,
110 * BOOLEAN printer-is-accepting-jobs)
111 * Printer's media-supported attribute has changed.
113 * PrinterAdded(STRING text,
114 * STRING printer-uri,
115 * STRING printer-name,
116 * UINT32 printer-state,
117 * STRING printer-state-reasons,
118 * BOOLEAN printer-is-accepting-jobs)
119 * Printer has been added.
121 * PrinterDeleted(STRING text,
122 * STRING printer-uri,
123 * STRING printer-name,
124 * UINT32 printer-state,
125 * STRING printer-state-reasons,
126 * BOOLEAN printer-is-accepting-jobs)
127 * Printer has been deleted.
129 * PrinterModified(STRING text,
130 * STRING printer-uri,
131 * STRING printer-name,
132 * UINT32 printer-state,
133 * STRING printer-state-reasons,
134 * BOOLEAN printer-is-accepting-jobs)
135 * Printer has been modified.
137 * text describes the event.
138 * printer-state-reasons is a comma-separated list.
139 * If printer-uri is "" in a Job* signal, the other printer-* parameters
141 * If the job name is not know, job-name will be "".
160 static int acquire_lock(int *fd
, char *lockfile
, size_t locksize
);
164 * 'main()' - Read events and send DBUS notifications.
167 int /* O - Exit status */
168 main(int argc
, /* I - Number of command-line args */
169 char *argv
[]) /* I - Command-line arguments */
171 ipp_t
*msg
; /* Event message from scheduler */
172 ipp_state_t state
; /* IPP event state */
173 struct sigaction action
; /* POSIX sigaction data */
174 DBusConnection
*con
= NULL
; /* Connection to DBUS server */
175 DBusError error
; /* Error, if any */
176 DBusMessage
*message
; /* Message to send */
177 DBusMessageIter iter
; /* Iterator for message data */
178 int lock_fd
= -1; /* Lock file descriptor */
179 char lock_filename
[1024];
184 * Don't buffer stderr...
187 setbuf(stderr
, NULL
);
190 * Ignore SIGPIPE signals...
193 memset(&action
, 0, sizeof(action
));
194 action
.sa_handler
= SIG_IGN
;
195 sigaction(SIGPIPE
, &action
, NULL
);
198 * Validate command-line options...
203 fputs("Usage: dbus dbus:/// notify-user-data\n", stderr
);
207 if (strncmp(argv
[1], "dbus:", 5))
209 fprintf(stderr
, "ERROR: Bad URI \"%s\"!\n", argv
[1]);
214 * Loop forever until we run out of events...
219 ipp_attribute_t
*attr
; /* Current attribute */
220 const char *event
; /* Event name */
221 const char *signame
= NULL
;/* DBUS signal name */
222 char *printer_reasons
= NULL
;
223 /* Printer reasons string */
224 char *job_reasons
= NULL
;
225 /* Job reasons string */
226 const char *nul
= ""; /* Empty string value */
227 int no
= 0; /* Boolean "no" value */
228 int params
= PARAMS_NONE
;
229 /* What parameters to include? */
233 * Get the next event...
237 while ((state
= ippReadFile(0, msg
)) != IPP_DATA
)
239 if (state
<= IPP_IDLE
)
243 fprintf(stderr
, "DEBUG: state=%d\n", state
);
245 if (state
== IPP_ERROR
)
246 fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr
);
248 if (state
<= IPP_IDLE
)
251 * Out of messages, free memory and then exit...
259 * Verify connection to DBUS server...
262 if (con
&& !dbus_connection_get_is_connected(con
))
264 dbus_connection_unref(con
);
270 dbus_error_init(&error
);
272 con
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
);
274 dbus_error_free(&error
);
276 fputs("DEBUG: Connected to D-BUS\n", stderr
);
283 acquire_lock(&lock_fd
, lock_filename
, sizeof(lock_filename
)))
286 attr
= ippFindAttribute(msg
, "notify-subscribed-event",
291 event
= ippGetString(attr
, 0, NULL
);
292 if (!strncmp(event
, "server-", 7))
294 const char *word2
= event
+ 7; /* Second word */
296 if (!strcmp(word2
, "restarted"))
297 signame
= "ServerRestarted";
298 else if (!strcmp(word2
, "started"))
299 signame
= "ServerStarted";
300 else if (!strcmp(word2
, "stopped"))
301 signame
= "ServerStopped";
302 else if (!strcmp(word2
, "audit"))
303 signame
= "ServerAudit";
307 else if (!strncmp(event
, "printer-", 8))
309 const char *word2
= event
+ 8; /* Second word */
311 params
= PARAMS_PRINTER
;
312 if (!strcmp(word2
, "restarted"))
313 signame
= "PrinterRestarted";
314 else if (!strcmp(word2
, "shutdown"))
315 signame
= "PrinterShutdown";
316 else if (!strcmp(word2
, "stopped"))
317 signame
= "PrinterStopped";
318 else if (!strcmp(word2
, "state-changed"))
319 signame
= "PrinterStateChanged";
320 else if (!strcmp(word2
, "finishings-changed"))
321 signame
= "PrinterFinishingsChanged";
322 else if (!strcmp(word2
, "media-changed"))
323 signame
= "PrinterMediaChanged";
324 else if (!strcmp(word2
, "added"))
325 signame
= "PrinterAdded";
326 else if (!strcmp(word2
, "deleted"))
327 signame
= "PrinterDeleted";
328 else if (!strcmp(word2
, "modified"))
329 signame
= "PrinterModified";
333 else if (!strncmp(event
, "job-", 4))
335 const char *word2
= event
+ 4; /* Second word */
338 if (!strcmp(word2
, "state-changed"))
339 signame
= "JobState";
340 else if (!strcmp(word2
, "created"))
341 signame
= "JobCreated";
342 else if (!strcmp(word2
, "completed"))
343 signame
= "JobCompleted";
344 else if (!strcmp(word2
, "stopped"))
345 signame
= "JobStopped";
346 else if (!strcmp(word2
, "config-changed"))
347 signame
= "JobConfigChanged";
348 else if (!strcmp(word2
, "progress"))
349 signame
= "JobProgress";
357 * Create and send the new message...
360 fprintf(stderr
, "DEBUG: %s\n", signame
);
361 message
= dbus_message_new_signal("/org/cups/cupsd/Notifier",
362 "org.cups.cupsd.Notifier",
365 dbus_message_append_iter_init(message
, &iter
);
366 attr
= ippFindAttribute(msg
, "notify-text", IPP_TAG_TEXT
);
369 const char *val
= ippGetString(attr
, 0, NULL
);
370 if (!dbus_message_iter_append_string(&iter
, &val
))
376 if (params
>= PARAMS_PRINTER
)
378 char *p
; /* Pointer into printer_reasons */
379 size_t reasons_length
; /* Required size of printer_reasons */
380 int i
; /* Looping var */
381 int have_printer_params
= 1;/* Do we have printer URI? */
383 /* STRING printer-uri or "" */
384 attr
= ippFindAttribute(msg
, "notify-printer-uri", IPP_TAG_URI
);
387 const char *val
= ippGetString(attr
, 0, NULL
);
388 if (!dbus_message_iter_append_string(&iter
, &val
))
393 have_printer_params
= 0;
394 dbus_message_iter_append_string(&iter
, &nul
);
397 /* STRING printer-name */
398 if (have_printer_params
)
400 attr
= ippFindAttribute(msg
, "printer-name", IPP_TAG_NAME
);
403 const char *val
= ippGetString(attr
, 0, NULL
);
404 if (!dbus_message_iter_append_string(&iter
, &val
))
411 dbus_message_iter_append_string(&iter
, &nul
);
413 /* UINT32 printer-state */
414 if (have_printer_params
)
416 attr
= ippFindAttribute(msg
, "printer-state", IPP_TAG_ENUM
);
419 dbus_uint32_t val
= ippGetInteger(attr
, 0);
420 dbus_message_iter_append_uint32(&iter
, &val
);
426 dbus_message_iter_append_uint32(&iter
, &no
);
428 /* STRING printer-state-reasons */
429 if (have_printer_params
)
431 attr
= ippFindAttribute(msg
, "printer-state-reasons",
435 int num_values
= ippGetCount(attr
);
436 for (reasons_length
= 0, i
= 0; i
< num_values
; i
++)
437 /* All need commas except the last, which needs a nul byte. */
438 reasons_length
+= 1 + strlen(ippGetString(attr
, i
, NULL
));
439 printer_reasons
= malloc(reasons_length
);
440 if (!printer_reasons
)
443 for (i
= 0; i
< num_values
; i
++)
448 strlcpy(p
, ippGetString(attr
, i
, NULL
),
449 reasons_length
- (p
- printer_reasons
));
452 if (!dbus_message_iter_append_string(&iter
, &printer_reasons
))
459 dbus_message_iter_append_string(&iter
, &nul
);
461 /* BOOL printer-is-accepting-jobs */
462 if (have_printer_params
)
464 attr
= ippFindAttribute(msg
, "printer-is-accepting-jobs",
468 dbus_bool_t val
= ippGetBoolean(attr
, 0);
469 dbus_message_iter_append_boolean(&iter
, &val
);
475 dbus_message_iter_append_boolean(&iter
, &no
);
478 if (params
>= PARAMS_JOB
)
480 char *p
; /* Pointer into job_reasons */
481 size_t reasons_length
; /* Required size of job_reasons */
482 int i
; /* Looping var */
485 attr
= ippFindAttribute(msg
, "notify-job-id", IPP_TAG_INTEGER
);
488 dbus_uint32_t val
= ippGetInteger(attr
, 0);
489 dbus_message_iter_append_uint32(&iter
, &val
);
494 /* UINT32 job-state */
495 attr
= ippFindAttribute(msg
, "job-state", IPP_TAG_ENUM
);
498 dbus_uint32_t val
= ippGetInteger(attr
, 0);
499 dbus_message_iter_append_uint32(&iter
, &val
);
504 /* STRING job-state-reasons */
505 attr
= ippFindAttribute(msg
, "job-state-reasons", IPP_TAG_KEYWORD
);
508 int num_values
= ippGetCount(attr
);
509 for (reasons_length
= 0, i
= 0; i
< num_values
; i
++)
510 /* All need commas except the last, which needs a nul byte. */
511 reasons_length
+= 1 + strlen(ippGetString(attr
, i
, NULL
));
512 job_reasons
= malloc(reasons_length
);
516 for (i
= 0; i
< num_values
; i
++)
521 strlcpy(p
, ippGetString(attr
, i
, NULL
),
522 reasons_length
- (p
- job_reasons
));
525 if (!dbus_message_iter_append_string(&iter
, &job_reasons
))
531 /* STRING job-name or "" */
532 attr
= ippFindAttribute(msg
, "job-name", IPP_TAG_NAME
);
535 const char *val
= ippGetString(attr
, 0, NULL
);
536 if (!dbus_message_iter_append_string(&iter
, &val
))
540 dbus_message_iter_append_string(&iter
, &nul
);
542 /* UINT32 job-impressions-completed */
543 attr
= ippFindAttribute(msg
, "job-impressions-completed",
547 dbus_uint32_t val
= ippGetInteger(attr
, 0);
548 dbus_message_iter_append_uint32(&iter
, &val
);
554 dbus_connection_send(con
, message
, NULL
);
555 dbus_connection_flush(con
);
563 dbus_message_unref(message
);
566 free(printer_reasons
);
575 * Remove lock file...
581 unlink(lock_filename
);
589 * 'acquire_lock()' - Acquire a lock so we only have a single notifier running.
592 static int /* O - 0 on success, -1 on failure */
593 acquire_lock(int *fd
, /* O - Lock file descriptor */
594 char *lockfile
, /* I - Lock filename buffer */
595 size_t locksize
) /* I - Size of filename buffer */
597 const char *tmpdir
; /* Temporary directory */
601 * Figure out where to put the lock file...
604 if ((tmpdir
= getenv("TMPDIR")) == NULL
)
607 snprintf(lockfile
, locksize
, "%s/cups-dbus-notifier-lockfile", tmpdir
);
610 * Create the lock file and fail if it already exists...
613 if ((*fd
= open(lockfile
, O_RDWR
| O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
)) < 0)
618 #else /* !HAVE_DBUS */
624 #endif /* HAVE_DBUS */