2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
21 #include "bus-internal.h"
23 #include "cgroup-util.h"
24 #include "conf-parser.h"
25 #include "dirent-util.h"
30 #include "unit-name.h"
33 static const char *arg_dest_late
= "/tmp", *arg_dest
= "/tmp";
35 static int create_dbus_files(
43 _cleanup_free_
char *b
= NULL
, *s
= NULL
, *lnk
= NULL
;
44 _cleanup_fclose_
FILE *f
= NULL
;
49 assert(service
|| exec
);
52 _cleanup_free_
char *a
= NULL
;
54 s
= strjoin("dbus-", name
, ".service", NULL
);
58 a
= strjoin(arg_dest_late
, "/", s
, NULL
);
64 return log_error_errno(errno
, "Failed to create %s: %m", a
);
67 "# Automatically generated by systemd-dbus1-generator\n\n"
70 "Description=DBUS1: %s\n"
71 "Documentation=man:systemd-dbus1-generator(8)\n\n"
82 fprintf(f
, "User=%s\n", user
);
86 fprintf(f
, "Environment=DBUS_STARTER_BUS_TYPE=%s\n", type
);
88 if (streq(type
, "system"))
89 fprintf(f
, "Environment=DBUS_STARTER_ADDRESS=" DEFAULT_SYSTEM_BUS_ADDRESS
"\n");
90 else if (streq(type
, "session")) {
93 run
= getenv("XDG_RUNTIME_DIR");
95 log_error("XDG_RUNTIME_DIR not set.");
99 fprintf(f
, "Environment=DBUS_STARTER_ADDRESS="KERNEL_USER_BUS_ADDRESS_FMT
";" UNIX_USER_BUS_ADDRESS_FMT
"\n",
104 r
= fflush_and_check(f
);
106 return log_error_errno(r
, "Failed to write %s: %m", a
);
113 b
= strjoin(arg_dest_late
, "/", name
, ".busname", NULL
);
119 return log_error_errno(errno
, "Failed to create %s: %m", b
);
122 "# Automatically generated by systemd-dbus1-generator\n\n"
125 "Description=DBUS1: %s\n"
126 "Documentation=man:systemd-dbus1-generator(8)\n\n"
136 r
= fflush_and_check(f
);
138 return log_error_errno(r
, "Failed to write %s: %m", b
);
140 lnk
= strjoin(arg_dest_late
, "/" SPECIAL_BUSNAMES_TARGET
".wants/", name
, ".busname", NULL
);
144 mkdir_parents_label(lnk
, 0755);
146 return log_error_errno(errno
, "Failed to create symlink %s: %m", lnk
);
151 static int add_dbus(const char *path
, const char *fname
, const char *type
) {
152 _cleanup_free_
char *name
= NULL
, *exec
= NULL
, *user
= NULL
, *service
= NULL
;
154 const ConfigTableItem table
[] = {
155 { "D-BUS Service", "Name", config_parse_string
, 0, &name
},
156 { "D-BUS Service", "Exec", config_parse_string
, 0, &exec
},
157 { "D-BUS Service", "User", config_parse_string
, 0, &user
},
158 { "D-BUS Service", "SystemdService", config_parse_string
, 0, &service
},
168 p
= strjoina(path
, "/", fname
);
169 r
= config_parse(NULL
, p
, NULL
,
171 config_item_table_lookup
, table
,
172 true, false, true, NULL
);
177 log_warning("Activation file %s lacks name setting, ignoring.", p
);
181 if (!service_name_is_valid(name
)) {
182 log_warning("Bus service name %s is not valid, ignoring.", name
);
186 if (streq(name
, "org.freedesktop.systemd1")) {
187 log_debug("Skipping %s, identified as systemd.", p
);
192 if (!unit_name_is_valid(service
, UNIT_NAME_PLAIN
|UNIT_NAME_INSTANCE
)) {
193 log_warning("Unit name %s is not valid, ignoring.", service
);
196 if (!endswith(service
, ".service")) {
197 log_warning("Bus names can only activate services, ignoring %s.", p
);
201 if (streq(exec
, "/bin/false") || !exec
) {
202 log_warning("Neither service name nor binary path specified, ignoring %s.", p
);
206 if (exec
[0] != '/') {
207 log_warning("Exec= in %s does not start with an absolute path, ignoring.", p
);
212 return create_dbus_files(p
, name
, service
, exec
, user
, type
);
215 static int parse_dbus_fragments(const char *path
, const char *type
) {
216 _cleanup_closedir_
DIR *d
= NULL
;
225 if (errno
== -ENOENT
)
228 return log_error_errno(errno
, "Failed to enumerate D-Bus activated services: %m");
232 FOREACH_DIRENT(de
, d
, goto fail
) {
235 if (!endswith(de
->d_name
, ".service"))
238 q
= add_dbus(path
, de
->d_name
, type
);
246 return log_error_errno(errno
, "Failed to read D-Bus services directory: %m");
249 static int link_busnames_target(const char *units
) {
252 f
= strjoina(units
, "/" SPECIAL_BUSNAMES_TARGET
);
253 t
= strjoina(arg_dest
, "/" SPECIAL_BASIC_TARGET
".wants/" SPECIAL_BUSNAMES_TARGET
);
255 mkdir_parents_label(t
, 0755);
256 if (symlink(f
, t
) < 0)
257 return log_error_errno(errno
, "Failed to create symlink %s: %m", t
);
262 static int link_compatibility(const char *units
) {
265 f
= strjoina(units
, "/systemd-bus-proxyd.socket");
266 t
= strjoina(arg_dest
, "/" SPECIAL_DBUS_SOCKET
);
267 mkdir_parents_label(t
, 0755);
268 if (symlink(f
, t
) < 0)
269 return log_error_errno(errno
, "Failed to create symlink %s: %m", t
);
271 f
= strjoina(units
, "/systemd-bus-proxyd.socket");
272 t
= strjoina(arg_dest
, "/" SPECIAL_SOCKETS_TARGET
".wants/systemd-bus-proxyd.socket");
273 mkdir_parents_label(t
, 0755);
274 if (symlink(f
, t
) < 0)
275 return log_error_errno(errno
, "Failed to create symlink %s: %m", t
);
277 t
= strjoina(arg_dest
, "/" SPECIAL_DBUS_SERVICE
);
278 if (symlink("/dev/null", t
) < 0)
279 return log_error_errno(errno
, "Failed to mask %s: %m", t
);
284 int main(int argc
, char *argv
[]) {
285 const char *path
, *type
, *units
;
288 if (argc
> 1 && argc
!= 4) {
289 log_error("This program takes three or no arguments.");
295 arg_dest_late
= argv
[3];
298 log_set_target(LOG_TARGET_SAFE
);
299 log_parse_environment();
304 if (!is_kdbus_available())
307 r
= cg_pid_get_owner_uid(0, NULL
);
309 path
= "/usr/share/dbus-1/services";
311 units
= USER_DATA_UNIT_PATH
;
312 } else if (r
== -ENXIO
) {
313 path
= "/usr/share/dbus-1/system-services";
315 units
= SYSTEM_DATA_UNIT_PATH
;
317 return log_error_errno(r
, "Failed to determine whether we are running as user or system instance: %m");
319 r
= parse_dbus_fragments(path
, type
);
321 /* FIXME: One day this should just be pulled in statically from basic.target */
322 q
= link_busnames_target(units
);
326 q
= link_compatibility(units
);
330 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;