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