chiark / gitweb /
machined: port over to libsystemd-bus
[elogind.git] / src / machine / machine-dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <string.h>
24
25 #include "bus-util.h"
26 #include "machine.h"
27
28 static int property_get_id(
29                 sd_bus *bus,
30                 const char *path,
31                 const char *interface,
32                 const char *property,
33                 sd_bus_message *reply,
34                 sd_bus_error *error,
35                 void *userdata) {
36
37         Machine *m = userdata;
38         int r;
39
40         assert(bus);
41         assert(reply);
42         assert(m);
43
44         r = sd_bus_message_append_array(reply, 'y', &m->id, 16);
45         if (r < 0)
46                 return r;
47
48         return 1;
49 }
50
51 static int property_get_state(
52                 sd_bus *bus,
53                 const char *path,
54                 const char *interface,
55                 const char *property,
56                 sd_bus_message *reply,
57                 sd_bus_error *error,
58                 void *userdata) {
59
60         Machine *m = userdata;
61         const char *state;
62         int r;
63
64         assert(bus);
65         assert(reply);
66         assert(m);
67
68         state = machine_state_to_string(machine_get_state(m));
69
70         r = sd_bus_message_append_basic(reply, 's', state);
71         if (r < 0)
72                 return r;
73
74         return 1;
75 }
76
77 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
78
79 static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata) {
80         Machine *m = userdata;
81         int r;
82
83         assert(bus);
84         assert(message);
85         assert(m);
86
87         r = machine_stop(m);
88         if (r < 0)
89                 return sd_bus_reply_method_errno(bus, message, r, NULL);
90
91         return sd_bus_reply_method_return(bus, message, NULL);
92 }
93
94 static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata) {
95         Machine *m = userdata;
96         const char *swho;
97         int32_t signo;
98         KillWho who;
99         int r;
100
101         assert(bus);
102         assert(message);
103         assert(m);
104
105         r = sd_bus_message_read(message, "si", &swho, &signo);
106         if (r < 0)
107                 return sd_bus_reply_method_errno(bus, message, r, NULL);
108
109         if (isempty(swho))
110                 who = KILL_ALL;
111         else {
112                 who = kill_who_from_string(swho);
113                 if (who < 0)
114                         return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
115         }
116
117         if (signo <= 0 || signo >= _NSIG)
118                 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
119
120         r = machine_kill(m, who, signo);
121         if (r < 0)
122                 return sd_bus_reply_method_errno(bus, message, r, NULL);
123
124         return sd_bus_reply_method_return(bus, message, NULL);
125 }
126
127 const sd_bus_vtable machine_vtable[] = {
128         SD_BUS_VTABLE_START(0),
129         SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), 0),
130         SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, 0),
131         SD_BUS_PROPERTY("Timestamp", "t", NULL, offsetof(Machine, timestamp.realtime), 0),
132         SD_BUS_PROPERTY("TimestampMonotonic", "t", NULL, offsetof(Machine, timestamp.monotonic), 0),
133         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), 0),
134         SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, scope), 0),
135         SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), 0),
136         SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), 0),
137         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
138         SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), 0),
139         SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0),
140         SD_BUS_METHOD("Kill", "si", NULL, method_kill, 0),
141         SD_BUS_VTABLE_END
142 };
143
144 int machine_object_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
145         _cleanup_free_ char *e = NULL;
146         Manager *m = userdata;
147         Machine *machine;
148         const char *p;
149
150         assert(bus);
151         assert(path);
152         assert(interface);
153         assert(found);
154         assert(m);
155
156         p = startswith(path, "/org/freedesktop/machine1/machine/");
157         if (!p)
158                 return 0;
159
160         e = bus_path_unescape(p);
161         if (!e)
162                 return -ENOMEM;
163
164         machine = hashmap_get(m->machines, e);
165         if (!machine)
166                 return 0;
167
168         *found = machine;
169         return 1;
170 }
171
172 char *machine_bus_path(Machine *m) {
173         _cleanup_free_ char *e = NULL;
174
175         assert(m);
176
177         e = bus_path_escape(m->name);
178         if (!e)
179                 return NULL;
180
181         return strappend("/org/freedesktop/machine1/machine/", e);
182 }
183
184 int machine_send_signal(Machine *m, bool new_machine) {
185         _cleanup_free_ char *p = NULL;
186
187         assert(m);
188
189         p = machine_bus_path(m);
190         if (!p)
191                 return -ENOMEM;
192
193         return sd_bus_emit_signal(
194                         m->manager->bus,
195                         "/org/freedesktop/machine1",
196                         "org.freedesktop.machine1.Manager",
197                         new_machine ? "MachineNew" : "MachineRemoved",
198                         "so", m->name, p);
199 }
200
201 int machine_send_create_reply(Machine *m, sd_bus_error *error) {
202         _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
203         _cleanup_free_ char *p = NULL;
204
205         assert(m);
206
207         if (!m->create_message)
208                 return 0;
209
210         c = m->create_message;
211         m->create_message = NULL;
212
213         /* Update the machine state file before we notify the client
214          * about the result. */
215         machine_save(m);
216
217         if (error)
218                 return sd_bus_reply_method_error(m->manager->bus, c, error);
219
220         p = machine_bus_path(m);
221         if (!p)
222                 return -ENOMEM;
223
224         return sd_bus_reply_method_return(m->manager->bus, c, "o", p);
225 }