chiark / gitweb /
[PATCH] udev_dbus changes
[elogind.git] / extras / dbus / udev_dbus.c
1 /*
2  * udev_dbus.c
3  *
4  * Copyright (C) 2003 David Zeuthen <david@fubar.dk>
5  *
6  *      This program is free software; you can redistribute it and/or modify it
7  *      under the terms of the GNU General Public License as published by the
8  *      Free Software Foundation version 2 of the License.
9  * 
10  *      This program is distributed in the hope that it will be useful, but
11  *      WITHOUT ANY WARRANTY; without even the implied warranty of
12  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *      General Public License for more details.
14  * 
15  *      You should have received a copy of the GNU General Public License along
16  *      with this program; if not, write to the Free Software Foundation, Inc.,
17  *      675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <ctype.h>
28
29 #define DBUS_API_SUBJECT_TO_CHANGE
30 #include <dbus/dbus.h>
31
32 #include "../../udev_lib.h"
33 #include "../../logging.h"
34
35 #ifdef LOG
36 unsigned char logname[LOGNAME_SIZE];
37 void log_message(int level, const char *format, ...)
38 {
39         va_list args;
40
41         va_start(args, format);
42         vsyslog(level, format, args);
43         va_end(args);
44 }
45 #endif
46
47 /*  Variable for the connection the to system message bus or NULL
48  *  if we cannot connect or acquire the org.kernel.udev service
49  */
50 static DBusConnection* sysbus_connection;
51
52 /* Disconnect from the system message bus */
53 static void sysbus_disconnect(void)
54 {
55         if (sysbus_connection == NULL)
56                 return;
57
58         dbus_connection_disconnect(sysbus_connection);
59         sysbus_connection = NULL;
60 }
61
62 /* Connect to the system message bus */
63 static void sysbus_connect(void)
64 {
65         DBusError error;
66
67         /* Connect to a well-known bus instance, the system bus */
68         dbus_error_init(&error);
69         sysbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
70         if (sysbus_connection == NULL) {
71                 dbg("cannot connect to system message bus, error %s: %s", 
72                     error.name, error.message);
73                 dbus_error_free(&error);
74                 return;
75         }
76
77         /*  Acquire the org.kernel.udev service such that listeners
78          *  know that the message is really from us and not from a
79          *  random attacker. See the file udev_sysbus_policy.conf for
80          *  details.
81          *
82          *  Note that a service can have multiple owners (though there
83          *  is a concept of a primary owner for reception of messages)
84          *  so no race is introduced if two copies of udev is running
85          *  at the same time.
86          */
87         dbus_bus_acquire_service(sysbus_connection, "org.kernel.udev", 0, 
88                                  &error);
89         if (dbus_error_is_set(&error)) {
90                 dbg("cannot acquire org.kernel.udev service, error %s: %s'",
91                     error.name, error.message);
92                 sysbus_disconnect();
93                 return;
94         }
95 }
96
97
98 /*  Send out a signal that a device node is created
99  *
100  *  @param  devname             Name of the device node, e.g. /dev/sda1
101  *  @param  path                Sysfs path of device
102  */
103 static void sysbus_send_create(const char *devname, const char *path)
104 {
105         DBusMessage* message;
106         DBusMessageIter iter;
107
108         /* object, interface, member */
109         message = dbus_message_new_signal("/org/kernel/udev/NodeMonitor", 
110                                           "org.kernel.udev.NodeMonitor",
111                                           "NodeCreated");
112
113         dbus_message_iter_init(message, &iter);
114         dbus_message_iter_append_string(&iter, devname);
115         dbus_message_iter_append_string(&iter, path);
116
117         if ( !dbus_connection_send(sysbus_connection, message, NULL) )
118                 dbg("error sending d-bus signal");
119
120         dbus_message_unref(message);
121
122         dbus_connection_flush(sysbus_connection);
123 }
124
125 /*  Send out a signal that a device node is deleted
126  *
127  *  @param  devname             Name of the device node, e.g. /udev/sda1
128  *  @param  path                Sysfs path of device
129  */
130 static void sysbus_send_remove(const char *devname, const char *path)
131 {
132         DBusMessage* message;
133         DBusMessageIter iter;
134
135         /* object, interface, member */
136         message = dbus_message_new_signal("/org/kernel/udev/NodeMonitor", 
137                                           "org.kernel.udev.NodeMonitor",
138                                           "NodeDeleted");
139
140         dbus_message_iter_init(message, &iter);
141         dbus_message_iter_append_string(&iter, devname);
142         dbus_message_iter_append_string(&iter, path);
143
144         if ( !dbus_connection_send(sysbus_connection, message, NULL) )
145                 dbg("error sending d-bus signal");
146
147         dbus_message_unref(message);
148
149         dbus_connection_flush(sysbus_connection);
150 }
151
152 int main(int argc, char *argv[], char *envp[])
153 {
154         char *action;
155         char *devpath;
156         char *devname;
157         int retval = 0;
158
159         init_logging("udev_dbus");
160
161         sysbus_connect();
162         if (sysbus_connection == NULL)
163                 return 0;
164
165         action = get_action();
166         if (!action) {
167                 dbg("no action?");
168                 goto exit;
169         }
170         devpath = get_devpath();
171         if (!devpath) {
172                 dbg("no devpath?");
173                 goto exit;
174         }
175         devname = get_devname();
176         if (!devname) {
177                 dbg("no devname?");
178                 goto exit;
179         }
180
181         if (strcmp(action, "add") == 0) {
182                 sysbus_send_create(devname, devpath);
183         } else {
184                 if (strcmp(action, "remove") == 0) {
185                         sysbus_send_remove(devname, devpath);
186                 } else {
187                         dbg("unknown action '%s'", action);
188                         retval = -EINVAL;
189                 }
190         }
191
192 exit:
193         sysbus_disconnect();
194         return retval;
195 }