]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/dbus1-generator/dbus1-generator.c
bus: skip unit file generation for systemd itself
[thirdparty/systemd.git] / src / dbus1-generator / dbus1-generator.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 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 "util.h"
23 #include "conf-parser.h"
24 #include "special.h"
25 #include "mkdir.h"
26 #include "bus-util.h"
27 #include "bus-internal.h"
28 #include "unit-name.h"
29 #include "cgroup-util.h"
30
31 static const char *arg_dest = "/tmp";
32
33 static int create_dbus_files(
34 const char *path,
35 const char *name,
36 const char *service,
37 const char *exec,
38 const char *user,
39 const char *type) {
40
41 _cleanup_free_ char *b = NULL, *s = NULL, *lnk = NULL;
42 _cleanup_fclose_ FILE *f = NULL;
43
44 assert(path);
45 assert(name);
46
47 if (!service) {
48 _cleanup_free_ char *a = NULL;
49
50 s = strjoin("dbus-", name, ".service", NULL);
51 if (!s)
52 return log_oom();
53
54 a = strjoin(arg_dest, "/", s, NULL);
55 if (!a)
56 return log_oom();
57
58 f = fopen(a, "wxe");
59 if (!f) {
60 log_error("Failed to create %s: %m", a);
61 return -errno;
62 }
63
64 fprintf(f,
65 "# Automatically generated by systemd-dbus1-generator\n\n"
66 "[Unit]\n"
67 "Source=%s\n"
68 "Description=DBUS1: %s\n\n"
69 "[Service]\n"
70 "ExecStart=%s\n"
71 "Type=dbus\n"
72 "BusName=%s\n",
73 path,
74 name,
75 exec,
76 name);
77
78 if (user)
79 fprintf(f, "User=%s\n", user);
80
81
82 if (type) {
83 fprintf(f, "Environment=DBUS_STARTER_BUS_TYPE=%s\n", type);
84
85 if (streq(type, "system"))
86 fprintf(f, "Environment=DBUS_STARTER_ADDRESS=kernel:/dev/kdbus/0-system\n");
87 else if (streq(type, "session"))
88 fprintf(f, "Environment=DBUS_STARTER_ADDRESS=kernel:/dev/kdbus/%lu-user\n", (unsigned long) getuid());
89 }
90
91 fflush(f);
92 if (ferror(f)) {
93 log_error("Failed to write %s: %m", a);
94 return -errno;
95 }
96
97 service = s;
98 }
99
100 b = strjoin(arg_dest, "/", name, ".busname", NULL);
101 if (!b)
102 return log_oom();
103
104 f = fopen(b, "wxe");
105 if (!f) {
106 log_error("Failed to create %s: %m", b);
107 return -errno;
108 }
109
110 fprintf(f,
111 "# Automatically generated by systemd-dbus1-generator\n\n"
112 "[Unit]\n"
113 "Source=%s\n"
114 "Description=DBUS1: %s\n\n"
115 "[BusName]\n"
116 "Name=%s\n"
117 "Service=%s\n",
118 path,
119 name,
120 name,
121 service);
122
123 fflush(f);
124 if (ferror(f)) {
125 log_error("Failed to write %s: %m", b);
126 return -errno;
127 }
128
129 lnk = strjoin(arg_dest, "/" SPECIAL_BUSNAMES_TARGET ".wants/", name, ".busname", NULL);
130 if (!lnk)
131 return log_oom();
132
133 mkdir_parents_label(lnk, 0755);
134 if (symlink(b, lnk)) {
135 log_error("Failed to create symlinks %s: %m", lnk);
136 return -errno;
137 }
138
139 return 0;
140 }
141
142 static int add_dbus(const char *path, const char *fname, const char *type) {
143 _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL;
144
145 ConfigTableItem table[] = {
146 { "D-BUS Service", "Name", config_parse_string, 0, &name },
147 { "D-BUS Service", "Exec", config_parse_string, 0, &exec },
148 { "D-BUS Service", "User", config_parse_string, 0, &user },
149 { "D-BUS Service", "SystemdService", config_parse_string, 0, &service },
150 };
151
152 _cleanup_fclose_ FILE *f = NULL;
153 _cleanup_free_ char *p = NULL;
154 int r;
155
156 assert(path);
157 assert(fname);
158
159 p = strjoin(path, "/", fname, NULL);
160 if (!p)
161 return log_oom();
162
163 f = fopen(p, "re");
164 if (!f) {
165 if (errno == -ENOENT)
166 return 0;
167
168 log_error("Failed to read %s: %m", p);
169 return -errno;
170 }
171
172 r = config_parse(NULL, p, f, "D-BUS Service\0", config_item_table_lookup, table, true, false, NULL);
173 if (r < 0)
174 return r;
175
176 if (!name) {
177 log_warning("Activation file %s lacks name setting, ignoring.", p);
178 return 0;
179 }
180
181 if (!service_name_is_valid(name)) {
182 log_warning("Bus service name %s is not valid, ignoring.", name);
183 return 0;
184 }
185
186 if (streq(name, "org.freedesktop.systemd1")) {
187 log_debug("Skipping %s, identified as systemd.", p);
188 return 0;
189 }
190
191 if (service) {
192 if (!unit_name_is_valid(service, false)) {
193 log_warning("Unit name %s is not valid, ignoring.", service);
194 return 0;
195 }
196 if (!endswith(service, ".service")) {
197 log_warning("Bus names can only activate services, ignoring %s.", p);
198 return 0;
199 }
200 } else {
201 if (streq(exec, "/bin/false") || !exec) {
202 log_warning("Neither service name nor binary path specified, ignoring %s.", p);
203 return 0;
204 }
205
206 if (exec[0] != '/') {
207 log_warning("Exec= in %s does not start with an absolute path, ignoring.", p);
208 return 0;
209 }
210 }
211
212 return create_dbus_files(p, name, service, exec, user, type);
213 }
214
215 static int parse_dbus_fragments(void) {
216 _cleanup_closedir_ DIR *d = NULL;
217 struct dirent *de;
218 const char *p, *type;
219 int r;
220
221 r = cg_pid_get_owner_uid(0, NULL);
222 if (r >= 0) {
223 p = "/usr/share/dbus-1/services";
224 type = "session";
225 } else if (r == -ENOENT) {
226 p = "/usr/share/dbus-1/system-services";
227 type = "system";
228 } else if (r < 0) {
229 log_error("Failed to determine whether we are running as user or system instance: %s", strerror(-r));
230 return r;
231 }
232
233 d = opendir(p);
234 if (!d) {
235 if (errno == -ENOENT)
236 return 0;
237
238 log_error("Failed to enumerate D-Bus activated services: %m");
239 return -errno;
240 }
241
242 r = 0;
243 FOREACH_DIRENT(de, d, goto fail) {
244 int q;
245
246 if (!endswith(de->d_name, ".service"))
247 continue;
248
249 q = add_dbus(p, de->d_name, type);
250 if (q < 0)
251 r = q;
252 }
253
254 return r;
255
256 fail:
257 log_error("Failed to read D-Bus services directory: %m");
258 return -errno;
259 }
260
261 int main(int argc, char *argv[]) {
262 int r;
263
264 if (argc > 1 && argc != 4) {
265 log_error("This program takes three or no arguments.");
266 return EXIT_FAILURE;
267 }
268
269 if (argc > 1)
270 arg_dest = argv[3];
271
272 log_set_target(LOG_TARGET_SAFE);
273 log_parse_environment();
274 log_open();
275
276 umask(0022);
277
278 if (access("/dev/kdbus/control", F_OK) < 0)
279 return 0;
280
281 r = parse_dbus_fragments();
282
283 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
284 }