chiark / gitweb /
955a3dbb49fe56d7336582532340aa3fc07d6795
[elogind.git] / extras / dbus / udev_dbus.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <errno.h>
7 #include <ctype.h>
8
9 #define DBUS_API_SUBJECT_TO_CHANGE
10 #include <dbus/dbus.h>
11
12 #include "../../udev_lib.h"
13 #include "../../logging.h"
14
15 #ifdef LOG
16 unsigned char logname[LOGNAME_SIZE];
17 void log_message(int level, const char *format, ...)
18 {
19         va_list args;
20
21         if (!udev_log)
22                 return;
23
24         va_start(args, format);
25         vsyslog(level, format, args);
26         va_end(args);
27 }
28 #endif
29
30 /** variable for the connection the to system message bus or #NULL
31  *  if we cannot connect or acquire the org.kernel.udev service
32  */
33 static DBusConnection* sysbus_connection;
34
35 /** Disconnect from the system message bus */
36 static void sysbus_disconnect(void)
37 {
38         if (sysbus_connection == NULL)
39                 return;
40
41         dbus_connection_disconnect(sysbus_connection);
42         sysbus_connection = NULL;
43 }
44
45 /** Connect to the system message bus */
46 static void sysbus_connect(void)
47 {
48         DBusError error;
49
50         /* Connect to a well-known bus instance, the system bus */
51         dbus_error_init(&error);
52         sysbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
53         if (sysbus_connection == NULL) {
54                 dbg("cannot connect to system message bus, error %s: %s", 
55                     error.name, error.message);
56                 dbus_error_free(&error);
57                 return;
58         }
59
60         /*  Acquire the org.kernel.udev service such that listeners
61          *  know that the message is really from us and not from a
62          *  random attacker. See the file udev_sysbus_policy.conf for
63          *  details.
64          *
65          *  Note that a service can have multiple owners (though there
66          *  is a concept of a primary owner for reception of messages)
67          *  so no race is introduced if two copies of udev is running
68          *  at the same time.
69          */
70         dbus_bus_acquire_service(sysbus_connection, "org.kernel.udev", 0, 
71                                  &error);
72         if (dbus_error_is_set(&error)) {
73                 printf("cannot acquire org.kernel.udev service, error %s: %s'",
74                        error.name, error.message);
75                 sysbus_disconnect();
76                 return;
77         }
78 }
79
80
81 /** Send out a signal that a device node is created
82  *
83  *  @param  devnode             name of the device node, e.g. /dev/sda1
84  *  @param  path                Sysfs path of device
85  */
86 static void sysbus_send_create(const char *devnode, const char *path)
87 {
88         DBusMessage* message;
89         DBusMessageIter iter;
90
91         /* object, interface, member */
92         message = dbus_message_new_signal("/org/kernel/udev/NodeMonitor", 
93                                           "org.kernel.udev.NodeMonitor",
94                                           "NodeCreated");
95
96         dbus_message_iter_init(message, &iter);
97         dbus_message_iter_append_string(&iter, devnode);
98         dbus_message_iter_append_string(&iter, path);
99
100         if ( !dbus_connection_send(sysbus_connection, message, NULL) )
101                 dbg("error sending d-bus signal");
102
103         dbus_message_unref(message);
104
105         dbus_connection_flush(sysbus_connection);
106 }
107
108 /** Send out a signal that a device node is deleted
109  *
110  *  @param  devnode             Name of the device node, e.g. /udev/sda1
111  *  @param  path                Sysfs path of device
112  */
113 static void sysbus_send_remove(const char *devnode, const char *path)
114 {
115         DBusMessage* message;
116         DBusMessageIter iter;
117
118         /* object, interface, member */
119         message = dbus_message_new_signal("/org/kernel/udev/NodeMonitor", 
120                                           "org.kernel.udev.NodeMonitor",
121                                           "NodeDeleted");
122
123         dbus_message_iter_init(message, &iter);
124         dbus_message_iter_append_string(&iter, devnode);
125         dbus_message_iter_append_string(&iter, path);
126
127         if ( !dbus_connection_send(sysbus_connection, message, NULL) )
128                 dbg("error sending d-bus signal");
129
130         dbus_message_unref(message);
131
132         dbus_connection_flush(sysbus_connection);
133 }
134
135 int main(int argc, char *argv[], char *envp[])
136 {
137         char *action;
138         char *devpath;
139         char *devnode;
140         int retval = 0;
141
142         init_logging("udev_dbus");
143
144         sysbus_connect();
145         if (sysbus_connection == NULL)
146                 return 0;
147
148         action = get_action();
149         if (!action) {
150                 dbg("no action?");
151                 goto exit;
152         }
153         devpath = get_devpath();
154         if (!devpath) {
155                 dbg("no devpath?");
156                 goto exit;
157         }
158         devnode = get_devnode();
159         if (!devnode) {
160                 dbg("no devnode?");
161                 goto exit;
162         }
163
164         if (strcmp(action, "add") == 0) {
165                 sysbus_send_create(devnode, devpath);
166         } else {
167                 if (strcmp(action, "remove") == 0) {
168                         sysbus_send_remove(devnode, devpath);
169                 } else {
170                         dbg("unknown action '%s'", action);
171                         retval = -EINVAL;
172                 }
173         }
174
175 exit:
176         sysbus_disconnect();
177         return retval;
178 }