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/>.
31 SystemdRunningAs arg_running_as = SYSTEMD_SYSTEM;
33 static int generate_path(char **var, char **filenames) {
36 _cleanup_strv_free_ char **ans = NULL;
39 STRV_FOREACH(filename, filenames) {
42 t = dirname_malloc(*filename);
46 r = strv_consume(&ans, t);
51 assert_se(strv_uniq(ans));
53 r = strv_extend(&ans, "");
57 *var = strv_join(ans, ":");
64 static int verify_socket(Unit *u) {
69 if (u->type != UNIT_SOCKET)
72 /* Cannot run this without the service being around */
74 /* This makes sure instance is created if necessary. */
75 r = socket_instantiate_service(SOCKET(u));
77 log_error_unit(u->id, "Socket %s cannot be started, failed to create instance.",
82 /* This checks both type of sockets */
83 if (UNIT_ISSET(SOCKET(u)->service)) {
86 service = SERVICE(UNIT_DEREF(SOCKET(u)->service));
87 log_debug_unit(u->id, "%s uses %s", u->id, UNIT(service)->id);
89 if (UNIT(service)->load_state != UNIT_LOADED) {
90 log_error_unit(u->id, "Service %s not loaded, %s cannot be started.",
91 UNIT(service)->id, u->id);
99 static int verify_executable(Unit *u, ExecCommand *exec) {
103 if (access(exec->path, X_OK) < 0) {
104 log_error_unit(u->id, "%s: command %s is not executable: %m",
112 static int verify_executables(Unit *u) {
119 exec = u->type == UNIT_SOCKET ? SOCKET(u)->control_command :
120 u->type == UNIT_MOUNT ? MOUNT(u)->control_command :
121 u->type == UNIT_SWAP ? SWAP(u)->control_command : NULL;
122 k = verify_executable(u, exec);
126 if (u->type == UNIT_SERVICE)
127 for (i = 0; i < ELEMENTSOF(SERVICE(u)->exec_command); i++) {
128 k = verify_executable(u, SERVICE(u)->exec_command[i]);
133 if (u->type == UNIT_SOCKET)
134 for (i = 0; i < ELEMENTSOF(SOCKET(u)->exec_command); i++) {
135 k = verify_executable(u, SOCKET(u)->exec_command[i]);
143 static int test_unit(Unit *u) {
144 _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
150 if (log_get_max_level() >= LOG_DEBUG)
151 unit_dump(u, stdout, "\t");
153 log_debug_unit(u->id, "Creating %s/start job", u->id);
154 r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, false, &err, &j);
155 if (sd_bus_error_is_set(&err))
156 log_error_unit(u->id, "Error: %s: %s",
157 err.name, err.message);
159 log_error_unit(u->id, "Failed to create %s/start: %s",
160 u->id, strerror(-r));
162 k = verify_socket(u);
166 k = verify_executables(u);
173 static int test_units(char **filenames) {
174 _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
179 _cleanup_free_ char *var;
184 Unit *units[strv_length(filenames)];
188 r = generate_path(&var, filenames);
190 log_error("Failed to generate unit load path: %s", strerror(-r));
194 assert_se(set_unit_path(var) >= 0);
196 r = manager_new(arg_running_as, true, &m);
198 log_error("Failed to initalize manager: %s", strerror(-r));
202 log_debug("Starting manager...");
204 r = manager_startup(m, serial, fdset);
206 log_error("Failed to start manager: %s", strerror(-r));
210 manager_clear_jobs(m);
212 log_debug("Loading remaining units from the command line...");
214 STRV_FOREACH(filename, filenames) {
215 log_debug("Handling %s...", *filename);
217 k = manager_load_unit(m, NULL, *filename, &err, &units[count]);
219 log_error("Failed to load %s: %s", *filename, strerror(-r));
227 for (i = 0; i < count; i++) {
228 k = test_unit(units[i]);
239 static void help(void) {
240 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
241 "Check if unit files can be correctly loaded.\n\n"
242 " -h --help Show this help\n"
243 " --version Show package version\n"
244 " --system Connect to system manager\n"
245 " --user Connect to user service manager\n",
246 program_invocation_short_name);
249 static int parse_argv(int argc, char *argv[]) {
256 static const struct option options[] = {
257 { "help", no_argument, NULL, 'h' },
258 { "version", no_argument, NULL, ARG_VERSION },
259 { "user", no_argument, NULL, ARG_USER },
260 { "system", no_argument, NULL, ARG_SYSTEM },
271 while ((c = getopt_long(argc, argv, ":h", options, NULL)) >= 0)
279 puts(PACKAGE_STRING);
280 puts(SYSTEMD_FEATURES);
284 arg_running_as = SYSTEMD_USER;
288 arg_running_as = SYSTEMD_SYSTEM;
292 log_error("Unknown option %s.", argv[optind-1]);
296 log_error("Missing argument to %s.", argv[optind-1]);
300 assert_not_reached("Unhandled option code.");
303 return 1; /* work to do */
306 int main(int argc, char *argv[]) {
309 log_parse_environment();
312 r = parse_argv(argc, argv);
316 r = test_units(argv + optind);
319 return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;