1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Zbigniew Jędrzejewski-Szmek
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.
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.
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/>.
24 #include "alloc-util.h"
25 #include "analyze-verify.h"
26 #include "bus-error.h"
31 #include "path-util.h"
34 static int generate_path(char **var
, char **filenames
) {
37 _cleanup_strv_free_
char **ans
= NULL
;
40 STRV_FOREACH(filename
, filenames
) {
43 t
= dirname_malloc(*filename
);
47 r
= strv_consume(&ans
, t
);
52 assert_se(strv_uniq(ans
));
54 r
= strv_extend(&ans
, "");
58 *var
= strv_join(ans
, ":");
65 static int verify_socket(Unit
*u
) {
70 if (u
->type
!= UNIT_SOCKET
)
73 /* Cannot run this without the service being around */
75 /* This makes sure instance is created if necessary. */
76 r
= socket_instantiate_service(SOCKET(u
));
78 log_unit_error_errno(u
, r
, "Socket cannot be started, failed to create instance: %m");
82 /* This checks both type of sockets */
83 if (UNIT_ISSET(SOCKET(u
)->service
)) {
86 service
= SERVICE(UNIT_DEREF(SOCKET(u
)->service
));
87 log_unit_debug(u
, "Using %s", UNIT(service
)->id
);
89 if (UNIT(service
)->load_state
!= UNIT_LOADED
) {
90 log_unit_error(u
, "Service %s not loaded, %s cannot be started.", UNIT(service
)->id
, u
->id
);
98 static int verify_executable(Unit
*u
, ExecCommand
*exec
) {
102 if (access(exec
->path
, X_OK
) < 0)
103 return log_unit_error_errno(u
, errno
, "Command %s is not executable: %m", exec
->path
);
108 static int verify_executables(Unit
*u
) {
115 exec
= u
->type
== UNIT_SOCKET
? SOCKET(u
)->control_command
:
116 u
->type
== UNIT_MOUNT
? MOUNT(u
)->control_command
:
117 u
->type
== UNIT_SWAP
? SWAP(u
)->control_command
: NULL
;
118 k
= verify_executable(u
, exec
);
122 if (u
->type
== UNIT_SERVICE
)
123 for (i
= 0; i
< ELEMENTSOF(SERVICE(u
)->exec_command
); i
++) {
124 k
= verify_executable(u
, SERVICE(u
)->exec_command
[i
]);
129 if (u
->type
== UNIT_SOCKET
)
130 for (i
= 0; i
< ELEMENTSOF(SOCKET(u
)->exec_command
); i
++) {
131 k
= verify_executable(u
, SOCKET(u
)->exec_command
[i
]);
139 static int verify_documentation(Unit
*u
, bool check_man
) {
143 STRV_FOREACH(p
, u
->documentation
) {
144 log_unit_debug(u
, "Found documentation item: %s", *p
);
146 if (check_man
&& startswith(*p
, "man:")) {
147 k
= show_man_page(*p
+ 4, true);
150 log_unit_error_errno(u
, r
, "Can't show %s: %m", *p
);
152 log_unit_error_errno(u
, r
, "man %s command failed with code %d", *p
+ 4, k
);
161 /* Check remote URLs? */
166 static int verify_unit(Unit
*u
, bool check_man
) {
167 _cleanup_(sd_bus_error_free
) sd_bus_error err
= SD_BUS_ERROR_NULL
;
172 if (log_get_max_level() >= LOG_DEBUG
)
173 unit_dump(u
, stdout
, "\t");
175 log_unit_debug(u
, "Creating %s/start job", u
->id
);
176 r
= manager_add_job(u
->manager
, JOB_START
, u
, JOB_REPLACE
, &err
, NULL
);
178 log_unit_error_errno(u
, r
, "Failed to create %s/start: %s", u
->id
, bus_error_message(&err
, r
));
180 k
= verify_socket(u
);
184 k
= verify_executables(u
);
188 k
= verify_documentation(u
, check_man
);
195 int verify_units(char **filenames
, ManagerRunningAs running_as
, bool check_man
) {
196 _cleanup_(sd_bus_error_free
) sd_bus_error err
= SD_BUS_ERROR_NULL
;
201 _cleanup_free_
char *var
= NULL
;
206 Unit
*units
[strv_length(filenames
)];
209 if (strv_isempty(filenames
))
213 r
= generate_path(&var
, filenames
);
215 return log_error_errno(r
, "Failed to generate unit load path: %m");
217 assert_se(set_unit_path(var
) >= 0);
219 r
= manager_new(running_as
, true, &m
);
221 return log_error_errno(r
, "Failed to initialize manager: %m");
223 log_debug("Starting manager...");
225 r
= manager_startup(m
, serial
, fdset
);
227 log_error_errno(r
, "Failed to start manager: %m");
231 manager_clear_jobs(m
);
233 log_debug("Loading remaining units from the command line...");
235 STRV_FOREACH(filename
, filenames
) {
236 char fname
[UNIT_NAME_MAX
+ 2 + 1] = "./";
238 log_debug("Handling %s...", *filename
);
240 /* manager_load_unit does not like pure basenames, so prepend
241 * the local directory, but only for valid names. manager_load_unit
242 * will print the error for other ones. */
243 if (!strchr(*filename
, '/') && strlen(*filename
) <= UNIT_NAME_MAX
) {
244 strncat(fname
+ 2, *filename
, UNIT_NAME_MAX
);
245 k
= manager_load_unit(m
, NULL
, fname
, &err
, &units
[count
]);
247 k
= manager_load_unit(m
, NULL
, *filename
, &err
, &units
[count
]);
249 log_error_errno(k
, "Failed to load %s: %m", *filename
);
256 for (i
= 0; i
< count
; i
++) {
257 k
= verify_unit(units
[i
], check_man
);