]>
git.ipfire.org Git - thirdparty/cups.git/blob - notifier/dbus.c
4 * D-Bus notifier for CUPS.
6 * Copyright 2008-2010 by Apple Inc.
7 * Copyright (C) 2007 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>
35 #include <dbus/dbus.h>
36 #ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND
37 # define dbus_message_append_iter_init dbus_message_iter_init_append
38 # define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, v)
39 # define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, v)
40 # define dbus_message_iter_append_boolean(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, v)
41 #endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
45 * D-Bus object: org.cups.cupsd.Notifier
46 * D-Bus object path: /org/cups/cupsd/Notifier
48 * D-Bus interface name: org.cups.cupsd.Notifier
52 * ServerRestarted(STRING text)
53 * Server has restarted.
55 * ServerStarted(STRING text)
58 * ServerStopped(STRING text)
61 * ServerAudit(STRING text)
62 * Security-related event.
64 * PrinterRestarted(STRING text,
66 * STRING printer-name,
67 * UINT32 printer-state,
68 * STRING printer-state-reasons,
69 * BOOLEAN printer-is-accepting-jobs)
70 * Printer has restarted.
72 * PrinterShutdown(STRING text,
74 * STRING printer-name,
75 * UINT32 printer-state,
76 * STRING printer-state-reasons,
77 * BOOLEAN printer-is-accepting-jobs)
78 * Printer has shutdown.
80 * PrinterStopped(STRING text,
82 * STRING printer-name,
83 * UINT32 printer-state,
84 * STRING printer-state-reasons,
85 * BOOLEAN printer-is-accepting-jobs)
86 * Printer has stopped.
88 * PrinterStateChanged(STRING text,
90 * STRING printer-name,
91 * UINT32 printer-state,
92 * STRING printer-state-reasons,
93 * BOOLEAN printer-is-accepting-jobs)
94 * Printer state has changed.
96 * PrinterFinishingsChanged(STRING text,
98 * STRING printer-name,
99 * UINT32 printer-state,
100 * STRING printer-state-reasons,
101 * BOOLEAN printer-is-accepting-jobs)
102 * Printer's finishings-supported attribute has changed.
104 * PrinterMediaChanged(STRING text,
105 * STRING printer-uri,
106 * STRING printer-name,
107 * UINT32 printer-state,
108 * STRING printer-state-reasons,
109 * BOOLEAN printer-is-accepting-jobs)
110 * Printer's media-supported attribute has changed.
112 * PrinterAdded(STRING text,
113 * STRING printer-uri,
114 * STRING printer-name,
115 * UINT32 printer-state,
116 * STRING printer-state-reasons,
117 * BOOLEAN printer-is-accepting-jobs)
118 * Printer has been added.
120 * PrinterDeleted(STRING text,
121 * STRING printer-uri,
122 * STRING printer-name,
123 * UINT32 printer-state,
124 * STRING printer-state-reasons,
125 * BOOLEAN printer-is-accepting-jobs)
126 * Printer has been deleted.
128 * PrinterModified(STRING text,
129 * STRING printer-uri,
130 * STRING printer-name,
131 * UINT32 printer-state,
132 * STRING printer-state-reasons,
133 * BOOLEAN printer-is-accepting-jobs)
134 * Printer has been modified.
136 * text describes the event.
137 * printer-state-reasons is a comma-separated list.
138 * If printer-uri is "" in a Job* signal, the other printer-* parameters
140 * If the job name is not know, job-name will be "".
159 static int acquire_lock(int *fd
, char *lockfile
, size_t locksize
);
163 * 'main()' - Read events and send DBUS notifications.
166 int /* O - Exit status */
167 main(int argc
, /* I - Number of command-line args */
168 char *argv
[]) /* I - Command-line arguments */
170 ipp_t
*msg
; /* Event message from scheduler */
171 ipp_state_t state
; /* IPP event state */
172 struct sigaction action
; /* POSIX sigaction data */
173 DBusConnection
*con
= NULL
; /* Connection to DBUS server */
174 DBusError error
; /* Error, if any */
175 DBusMessage
*message
; /* Message to send */
176 DBusMessageIter iter
; /* Iterator for message data */
177 int lock_fd
= -1; /* Lock file descriptor */
178 char lock_filename
[1024];
183 * Don't buffer stderr...
186 setbuf(stderr
, NULL
);
189 * Ignore SIGPIPE signals...
192 memset(&action
, 0, sizeof(action
));
193 action
.sa_handler
= SIG_IGN
;
194 sigaction(SIGPIPE
, &action
, NULL
);
197 * Validate command-line options...
202 fputs("Usage: dbus dbus:/// notify-user-data\n", stderr
);
206 if (strncmp(argv
[1], "dbus:", 5))
208 fprintf(stderr
, "ERROR: Bad URI \"%s\"!\n", argv
[1]);
213 * Loop forever until we run out of events...
218 ipp_attribute_t
*attr
; /* Current attribute */
219 const char *event
; /* Event name */
220 const char *signame
= NULL
;/* DBUS signal name */
221 char *printer_reasons
= NULL
;
222 /* Printer reasons string */
223 const char *nul
= ""; /* Empty string value */
224 int no
= 0; /* Boolean "no" value */
225 int params
= PARAMS_NONE
;
226 /* What parameters to include? */
230 * Get the next event...
234 while ((state
= ippReadFile(0, msg
)) != IPP_DATA
)
236 if (state
<= IPP_IDLE
)
240 fprintf(stderr
, "DEBUG: state=%d\n", state
);
242 if (state
== IPP_ERROR
)
243 fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr
);
245 if (state
<= IPP_IDLE
)
248 * Out of messages, free memory and then exit...
256 * Verify connection to DBUS server...
259 if (con
&& !dbus_connection_get_is_connected(con
))
261 dbus_connection_unref(con
);
267 dbus_error_init(&error
);
269 con
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
);
271 dbus_error_free(&error
);
273 fputs("DEBUG: Connected to D-BUS\n", stderr
);
280 acquire_lock(&lock_fd
, lock_filename
, sizeof(lock_filename
)))
283 attr
= ippFindAttribute(msg
, "notify-subscribed-event",
288 event
= attr
->values
[0].string
.text
;
289 if (!strncmp(event
, "server-", 7))
291 const char *word2
= event
+ 7; /* Second word */
293 if (!strcmp(word2
, "restarted"))
294 signame
= "ServerRestarted";
295 else if (!strcmp(word2
, "started"))
296 signame
= "ServerStarted";
297 else if (!strcmp(word2
, "stopped"))
298 signame
= "ServerStopped";
299 else if (!strcmp(word2
, "audit"))
300 signame
= "ServerAudit";
304 else if (!strncmp(event
, "printer-", 8))
306 const char *word2
= event
+ 8; /* Second word */
308 params
= PARAMS_PRINTER
;
309 if (!strcmp(word2
, "restarted"))
310 signame
= "PrinterRestarted";
311 else if (!strcmp(word2
, "shutdown"))
312 signame
= "PrinterShutdown";
313 else if (!strcmp(word2
, "stopped"))
314 signame
= "PrinterStopped";
315 else if (!strcmp(word2
, "state-changed"))
316 signame
= "PrinterStateChanged";
317 else if (!strcmp(word2
, "finishings-changed"))
318 signame
= "PrinterFinishingsChanged";
319 else if (!strcmp(word2
, "media-changed"))
320 signame
= "PrinterMediaChanged";
321 else if (!strcmp(word2
, "added"))
322 signame
= "PrinterAdded";
323 else if (!strcmp(word2
, "deleted"))
324 signame
= "PrinterDeleted";
325 else if (!strcmp(word2
, "modified"))
326 signame
= "PrinterModified";
330 else if (!strncmp(event
, "job-", 4))
332 const char *word2
= event
+ 4; /* Second word */
335 if (!strcmp(word2
, "state-changed"))
336 signame
= "JobState";
337 else if (!strcmp(word2
, "created"))
338 signame
= "JobCreated";
339 else if (!strcmp(word2
, "completed"))
340 signame
= "JobCompleted";
341 else if (!strcmp(word2
, "stopped"))
342 signame
= "JobStopped";
343 else if (!strcmp(word2
, "config-changed"))
344 signame
= "JobConfigChanged";
345 else if (!strcmp(word2
, "progress"))
346 signame
= "JobProgress";
354 * Create and send the new message...
357 fprintf(stderr
, "DEBUG: %s\n", signame
);
358 message
= dbus_message_new_signal("/org/cups/cupsd/Notifier",
359 "org.cups.cupsd.Notifier",
362 dbus_message_append_iter_init(message
, &iter
);
363 attr
= ippFindAttribute(msg
, "notify-text", IPP_TAG_TEXT
);
366 dbus_message_iter_append_string(&iter
, &(attr
->values
[0].string
.text
));
368 if (params
>= PARAMS_PRINTER
)
370 char *p
; /* Pointer into printer_reasons */
371 size_t reasons_length
; /* Required size of printer_reasons */
372 int i
; /* Looping var */
373 int have_printer_params
= 1;/* Do we have printer URI? */
375 /* STRING printer-uri or "" */
376 attr
= ippFindAttribute(msg
, "notify-printer-uri", IPP_TAG_URI
);
378 dbus_message_iter_append_string(&iter
, &(attr
->values
[0].string
.text
));
381 have_printer_params
= 0;
382 dbus_message_iter_append_string(&iter
, &nul
);
385 /* STRING printer-name */
386 if (have_printer_params
)
388 attr
= ippFindAttribute(msg
, "printer-name", IPP_TAG_NAME
);
390 dbus_message_iter_append_string(&iter
,
391 &(attr
->values
[0].string
.text
));
396 dbus_message_iter_append_string(&iter
, &nul
);
398 /* UINT32 printer-state */
399 if (have_printer_params
)
401 attr
= ippFindAttribute(msg
, "printer-state", IPP_TAG_ENUM
);
403 dbus_message_iter_append_uint32(&iter
, &(attr
->values
[0].integer
));
408 dbus_message_iter_append_uint32(&iter
, &no
);
410 /* STRING printer-state-reasons */
411 if (have_printer_params
)
413 attr
= ippFindAttribute(msg
, "printer-state-reasons",
417 for (reasons_length
= 0, i
= 0; i
< attr
->num_values
; i
++)
418 /* All need commas except the last, which needs a nul byte. */
419 reasons_length
+= 1 + strlen(attr
->values
[i
].string
.text
);
420 printer_reasons
= malloc(reasons_length
);
421 if (!printer_reasons
)
424 for (i
= 0; i
< attr
->num_values
; i
++)
426 strcpy(p
, attr
->values
[i
].string
.text
);
431 dbus_message_iter_append_string(&iter
, &printer_reasons
);
437 dbus_message_iter_append_string(&iter
, &nul
);
439 /* BOOL printer-is-accepting-jobs */
440 if (have_printer_params
)
442 attr
= ippFindAttribute(msg
, "printer-is-accepting-jobs",
445 dbus_message_iter_append_boolean(&iter
, &(attr
->values
[0].boolean
));
450 dbus_message_iter_append_boolean(&iter
, &no
);
453 if (params
>= PARAMS_JOB
)
456 attr
= ippFindAttribute(msg
, "notify-job-id", IPP_TAG_INTEGER
);
459 dbus_message_iter_append_uint32(&iter
, &(attr
->values
[0].integer
));
461 /* UINT32 job-state */
462 attr
= ippFindAttribute(msg
, "job-state", IPP_TAG_ENUM
);
465 dbus_message_iter_append_uint32(&iter
, &(attr
->values
[0].integer
));
467 /* STRING job-state-reasons */
468 attr
= ippFindAttribute(msg
, "job-state-reasons", IPP_TAG_KEYWORD
);
471 dbus_message_iter_append_string(&iter
, &(attr
->values
[0].string
.text
));
473 /* STRING job-name or "" */
474 attr
= ippFindAttribute(msg
, "job-name", IPP_TAG_NAME
);
476 dbus_message_iter_append_string(&iter
, &(attr
->values
[0].string
.text
));
478 dbus_message_iter_append_string(&iter
, &nul
);
480 /* UINT32 job-impressions-completed */
481 attr
= ippFindAttribute(msg
, "job-impressions-completed",
485 dbus_message_iter_append_uint32(&iter
, &(attr
->values
[0].integer
));
488 dbus_connection_send(con
, message
, NULL
);
489 dbus_connection_flush(con
);
498 free(printer_reasons
);
500 dbus_message_unref(message
);
505 * Remove lock file...
511 unlink(lock_filename
);
519 * 'acquire_lock()' - Acquire a lock so we only have a single notifier running.
522 static int /* O - 0 on success, -1 on failure */
523 acquire_lock(int *fd
, /* O - Lock file descriptor */
524 char *lockfile
, /* I - Lock filename buffer */
525 size_t locksize
) /* I - Size of filename buffer */
527 const char *tmpdir
; /* Temporary directory */
531 * Figure out where to put the lock file...
534 if ((tmpdir
= getenv("TMPDIR")) == NULL
)
537 snprintf(lockfile
, locksize
, "%s/cups-dbus-notifier-lockfile", tmpdir
);
540 * Create the lock file and fail if it already exists...
543 if ((*fd
= open(lockfile
, O_RDWR
| O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
)) < 0)