]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/machine/machinectl.c
coccinelle: make use of SYNTHETIC_ERRNO
[thirdparty/systemd.git] / src / machine / machinectl.c
index f937cf7b93ed742991bd497394f5f9df5031d3b6..094ee9d360e508f7133241e69ec3b69dd7c689de 100644 (file)
@@ -22,6 +22,7 @@
 #include "cgroup-show.h"
 #include "cgroup-util.h"
 #include "copy.h"
+#include "def.h"
 #include "env-util.h"
 #include "fd-util.h"
 #include "format-table.h"
 #include "log.h"
 #include "logs-show.h"
 #include "macro.h"
+#include "main-func.h"
 #include "mkdir.h"
 #include "pager.h"
 #include "parse-util.h"
 #include "path-util.h"
+#include "pretty-print.h"
 #include "process-util.h"
 #include "ptyfwd.h"
+#include "rlimit-util.h"
 #include "sigbus.h"
 #include "signal-util.h"
 #include "spawn-polkit-agent.h"
@@ -55,12 +59,12 @@ static char **arg_property = NULL;
 static bool arg_all = false;
 static bool arg_value = false;
 static bool arg_full = false;
-static bool arg_no_pager = false;
+static PagerFlags arg_pager_flags = 0;
 static bool arg_legend = true;
 static const char *arg_kill_who = NULL;
 static int arg_signal = SIGTERM;
 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static char *arg_host = NULL;
+static const char *arg_host = NULL;
 static bool arg_read_only = false;
 static bool arg_mkdir = false;
 static bool arg_quiet = false;
@@ -74,6 +78,9 @@ static const char *arg_uid = NULL;
 static char **arg_setenv = NULL;
 static int arg_addrs = 1;
 
+STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep);
+
 static OutputFlags get_output_flags(void) {
         return
                 arg_all * OUTPUT_SHOW_ALL |
@@ -276,7 +283,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
 
         assert(bus);
 
-        (void) pager_open(arg_no_pager, false);
+        (void) pager_open(arg_pager_flags);
 
         r = sd_bus_call_method(bus,
                                "org.freedesktop.machine1",
@@ -356,7 +363,7 @@ static int list_images(int argc, char *argv[], void *userdata) {
 
         assert(bus);
 
-        (void) pager_open(arg_no_pager, false);
+        (void) pager_open(arg_pager_flags);
 
         r = sd_bus_call_method(bus,
                                "org.freedesktop.machine1",
@@ -540,7 +547,7 @@ typedef struct MachineStatusInfo {
         pid_t leader;
         struct dual_timestamp timestamp;
         int *netif;
-        unsigned n_netif;
+        size_t n_netif;
 } MachineStatusInfo;
 
 static void machine_status_info_clear(MachineStatusInfo *info) {
@@ -600,7 +607,7 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
                 printf("\t    Root: %s\n", i->root_directory);
 
         if (i->n_netif > 0) {
-                unsigned c;
+                size_t c;
 
                 fputs("\t   Iface:", stdout);
 
@@ -751,7 +758,7 @@ static int show_machine(int argc, char *argv[], void *userdata) {
 
         properties = !strstr(argv[0], "status");
 
-        (void) pager_open(arg_no_pager, false);
+        (void) pager_open(arg_pager_flags);
 
         if (properties && argc <= 1) {
 
@@ -773,10 +780,8 @@ static int show_machine(int argc, char *argv[], void *userdata) {
                                        &error,
                                        &reply,
                                        "s", argv[i]);
-                if (r < 0) {
-                        log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
-                        return r;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Could not get path to machine: %s", bus_error_message(&error, -r));
 
                 r = sd_bus_message_read(reply, "o", &path);
                 if (r < 0)
@@ -1091,7 +1096,7 @@ static int show_image(int argc, char *argv[], void *userdata) {
 
         properties = !strstr(argv[0], "status");
 
-        (void) pager_open(arg_no_pager, false);
+        (void) pager_open(arg_pager_flags);
 
         if (argc <= 1) {
 
@@ -1118,10 +1123,8 @@ static int show_image(int argc, char *argv[], void *userdata) {
                                 &error,
                                 &reply,
                                 "s", argv[i]);
-                if (r < 0) {
-                        log_error("Could not get path to image: %s", bus_error_message(&error, -r));
-                        return r;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Could not get path to image: %s", bus_error_message(&error, -r));
 
                 r = sd_bus_message_read(reply, "o", &path);
                 if (r < 0)
@@ -1158,10 +1161,8 @@ static int kill_machine(int argc, char *argv[], void *userdata) {
                                 &error,
                                 NULL,
                                 "ssi", argv[i], arg_kill_who, arg_signal);
-                if (r < 0) {
-                        log_error("Could not kill machine: %s", bus_error_message(&error, -r));
-                        return r;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Could not kill machine: %s", bus_error_message(&error, -r));
         }
 
         return 0;
@@ -1200,10 +1201,8 @@ static int terminate_machine(int argc, char *argv[], void *userdata) {
                                 &error,
                                 NULL,
                                 "s", argv[i]);
-                if (r < 0) {
-                        log_error("Could not terminate machine: %s", bus_error_message(&error, -r));
-                        return r;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Could not terminate machine: %s", bus_error_message(&error, -r));
         }
 
         return 0;
@@ -1285,10 +1284,8 @@ static int bind_mount(int argc, char *argv[], void *userdata) {
                         argv[3],
                         arg_read_only,
                         arg_mkdir);
-        if (r < 0) {
-                log_error("Failed to bind mount: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to bind mount: %s", bus_error_message(&error, -r));
 
         return 0;
 }
@@ -1335,8 +1332,8 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT
                         log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name);
         }
 
-        sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
-        sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+        (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+        (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
 
         r = pty_forward_new(event, master, flags, forward);
         if (r < 0)
@@ -1459,10 +1456,8 @@ static int login_machine(int argc, char *argv[], void *userdata) {
                         &error,
                         &reply,
                         "s", machine);
-        if (r < 0) {
-                log_error("Failed to get login PTY: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to get login PTY: %s", bus_error_message(&error, -r));
 
         r = sd_bus_message_read(reply, "hs", &master, NULL);
         if (r < 0)
@@ -1550,10 +1545,8 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
                 return bus_log_create_error(r);
 
         r = sd_bus_call(bus, m, 0, &error, &reply);
-        if (r < 0) {
-                log_error("Failed to get shell PTY: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to get shell PTY: %s", bus_error_message(&error, -r));
 
         r = sd_bus_message_read(reply, "hs", &master, NULL);
         if (r < 0)
@@ -1615,10 +1608,8 @@ static int rename_image(int argc, char *argv[], void *userdata) {
                         &error,
                         NULL,
                         "ss", argv[1], argv[2]);
-        if (r < 0) {
-                log_error("Could not rename image: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not rename image: %s", bus_error_message(&error, -r));
 
         return 0;
 }
@@ -1681,10 +1672,8 @@ static int read_only_image(int argc, char *argv[], void *userdata) {
                         &error,
                         NULL,
                         "sb", argv[1], b);
-        if (r < 0) {
-                log_error("Could not mark image read-only: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, -r));
 
         return 0;
 }
@@ -1721,10 +1710,9 @@ static int make_service_name(const char *name, char **ret) {
         assert(name);
         assert(ret);
 
-        if (!machine_name_is_valid(name)) {
-                log_error("Invalid machine name %s.", name);
-                return -EINVAL;
-        }
+        if (!machine_name_is_valid(name))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "Invalid machine name %s.", name);
 
         r = unit_name_build("systemd-nspawn", name, ".service", ret);
         if (r < 0)
@@ -1773,10 +1761,8 @@ static int start_machine(int argc, char *argv[], void *userdata) {
                                 &error,
                                 &reply,
                                 "ss", unit, "fail");
-                if (r < 0) {
-                        log_error("Failed to start unit: %s", bus_error_message(&error, -r));
-                        return r;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to start unit: %s", bus_error_message(&error, -r));
 
                 r = sd_bus_message_read(reply, "o", &object);
                 if (r < 0)
@@ -1855,10 +1841,8 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
                 return bus_log_create_error(r);
 
         r = sd_bus_call(bus, m, 0, &error, &reply);
-        if (r < 0) {
-                log_error("Failed to enable or disable unit: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to enable or disable unit: %s", bus_error_message(&error, -r));
 
         if (streq(argv[0], "enable")) {
                 r = sd_bus_message_read(reply, "b", NULL);
@@ -1993,10 +1977,8 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
                 return log_error_errno(r, "Failed to request match: %m");
 
         r = sd_bus_call(bus, m, 0, &error, &reply);
-        if (r < 0) {
-                log_error("Failed to transfer image: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to transfer image: %s", bus_error_message(&error, -r));
 
         r = sd_bus_message_read(reply, "uo", &id, &path);
         if (r < 0)
@@ -2007,8 +1989,8 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
         if (!arg_quiet)
                 log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id);
 
-        sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id));
-        sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id));
+        (void) sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id));
+        (void) sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id));
 
         r = sd_event_loop(event);
         if (r < 0)
@@ -2402,10 +2384,8 @@ typedef struct TransferInfo {
         double progress;
 } TransferInfo;
 
-static int compare_transfer_info(const void *a, const void *b) {
-        const TransferInfo *x = a, *y = b;
-
-        return strcmp(x->local, y->local);
+static int compare_transfer_info(const TransferInfo *a, const TransferInfo *b) {
+        return strcmp(a->local, b->local);
 }
 
 static int list_transfers(int argc, char *argv[], void *userdata) {
@@ -2420,7 +2400,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
         double progress;
         int r;
 
-        (void) pager_open(arg_no_pager, false);
+        (void) pager_open(arg_pager_flags);
 
         r = sd_bus_call_method(bus,
                                "org.freedesktop.import1",
@@ -2430,10 +2410,8 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
                                &error,
                                &reply,
                                NULL);
-        if (r < 0) {
-                log_error("Could not get transfers: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not get transfers: %s", bus_error_message(&error, -r));
 
         r = sd_bus_message_enter_container(reply, 'a', "(usssdo)");
         if (r < 0)
@@ -2475,7 +2453,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        qsort_safe(transfers, n_transfers, sizeof(TransferInfo), compare_transfer_info);
+        typesafe_qsort(transfers, n_transfers, compare_transfer_info);
 
         if (arg_legend && n_transfers > 0)
                 printf("%-*s %-*s %-*s %-*s %-*s\n",
@@ -2528,10 +2506,8 @@ static int cancel_transfer(int argc, char *argv[], void *userdata) {
                                 &error,
                                 NULL,
                                 "u", id);
-                if (r < 0) {
-                        log_error("Could not cancel transfer: %s", bus_error_message(&error, -r));
-                        return r;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Could not cancel transfer: %s", bus_error_message(&error, -r));
         }
 
         return 0;
@@ -2637,7 +2613,14 @@ static int clean_images(int argc, char *argv[], void *userdata) {
 }
 
 static int help(int argc, char *argv[], void *userdata) {
-        (void) pager_open(arg_no_pager, false);
+        _cleanup_free_ char *link = NULL;
+        int r;
+
+        (void) pager_open(arg_pager_flags);
+
+        r = terminal_urlify_man("machinectl", "1", &link);
+        if (r < 0)
+                return log_oom();
 
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
                "Send control commands to or query the virtual machine and container\n"
@@ -2665,7 +2648,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "  -o --output=STRING          Change journal output mode (short, short-precise,\n"
                "                               short-iso, short-iso-precise, short-full,\n"
                "                               short-monotonic, short-unix, verbose, export,\n"
-               "                               json, json-pretty, json-sse, cat)\n"
+               "                               json, json-pretty, json-sse, json-seq, cat,\n"
+               "                               with-unit)\n"
                "     --verify=MODE            Verification mode for downloaded images (no,\n"
                "                              checksum, signature)\n"
                "     --force                  Download image even if already exists\n\n"
@@ -2707,7 +2691,10 @@ static int help(int argc, char *argv[], void *userdata) {
                "  export-raw NAME [FILE]      Export a RAW container or VM image locally\n"
                "  list-transfers              Show list of downloads in progress\n"
                "  cancel-transfer             Cancel a download\n"
-               , program_invocation_short_name);
+               "\nSee the %s for details.\n"
+               , program_invocation_short_name
+               , link
+        );
 
         return 0;
 }
@@ -2849,10 +2836,9 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'n':
-                        if (safe_atou(optarg, &arg_lines) < 0) {
-                                log_error("Failed to parse lines '%s'", optarg);
-                                return -EINVAL;
-                        }
+                        if (safe_atou(optarg, &arg_lines) < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Failed to parse lines '%s'", optarg);
                         break;
 
                 case 'o':
@@ -2862,14 +2848,13 @@ static int parse_argv(int argc, char *argv[]) {
                         }
 
                         arg_output = output_mode_from_string(optarg);
-                        if (arg_output < 0) {
-                                log_error("Unknown output '%s'.", optarg);
-                                return -EINVAL;
-                        }
+                        if (arg_output < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Unknown output '%s'.", optarg);
                         break;
 
                 case ARG_NO_PAGER:
-                        arg_no_pager = true;
+                        arg_pager_flags |= PAGER_DISABLE;
                         break;
 
                 case ARG_NO_LEGEND:
@@ -2887,10 +2872,9 @@ static int parse_argv(int argc, char *argv[]) {
                         }
 
                         arg_signal = signal_from_string(optarg);
-                        if (arg_signal < 0) {
-                                log_error("Failed to parse signal string %s.", optarg);
-                                return -EINVAL;
-                        }
+                        if (arg_signal < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Failed to parse signal string %s.", optarg);
                         break;
 
                 case ARG_NO_ASK_PASSWORD:
@@ -2926,10 +2910,9 @@ static int parse_argv(int argc, char *argv[]) {
                         }
 
                         arg_verify = import_verify_from_string(optarg);
-                        if (arg_verify < 0) {
-                                log_error("Failed to parse --verify= setting: %s", optarg);
-                                return -EINVAL;
-                        }
+                        if (arg_verify < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Failed to parse --verify= setting: %s", optarg);
                         break;
 
                 case ARG_FORCE:
@@ -2937,10 +2920,9 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_FORMAT:
-                        if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) {
-                                log_error("Unknown format: %s", optarg);
-                                return -EINVAL;
-                        }
+                        if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2"))
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Unknown format: %s", optarg);
 
                         arg_format = optarg;
                         break;
@@ -2950,10 +2932,9 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'E':
-                        if (!env_assignment_is_valid(optarg)) {
-                                log_error("Environment assignment invalid: %s", optarg);
-                                return -EINVAL;
-                        }
+                        if (!env_assignment_is_valid(optarg))
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Environment assignment invalid: %s", optarg);
 
                         r = strv_extend(&arg_setenv, optarg);
                         if (r < 0)
@@ -2963,13 +2944,12 @@ static int parse_argv(int argc, char *argv[]) {
                 case ARG_NUMBER_IPS:
                         if (streq(optarg, "all"))
                                 arg_addrs = ALL_IP_ADDRESSES;
-                        else if (safe_atoi(optarg, &arg_addrs) < 0) {
-                                log_error("Invalid number of IPs");
-                                return -EINVAL;
-                        } else if (arg_addrs < 0) {
-                                log_error("Number of IPs cannot be negative");
-                                return -EINVAL;
-                        }
+                        else if (safe_atoi(optarg, &arg_addrs) < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Invalid number of IPs");
+                        else if (arg_addrs < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Number of IPs cannot be negative");
                         break;
 
                 case '?':
@@ -3042,38 +3022,30 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
         return dispatch_verb(argc, argv, verbs, bus);
 }
 
-int main(int argc, char*argv[]) {
-        sd_bus *bus = NULL;
+static int run(int argc, char*argv[]) {
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
         log_parse_environment();
         log_open();
+
+        /* The journal merging logic potentially needs a lot of fds. */
+        (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
+
         sigbus_install();
 
         r = parse_argv(argc, argv);
         if (r <= 0)
-                goto finish;
+                return r;
 
         r = bus_connect_transport(arg_transport, arg_host, false, &bus);
-        if (r < 0) {
-                log_error_errno(r, "Failed to create bus connection: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to create bus connection: %m");
 
         (void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
 
-        r = machinectl_main(argc, argv, bus);
-
-finish:
-        /* make sure we terminate the bus connection first, and then close the
-         * pager, see issue #3543 for the details. */
-        sd_bus_flush_close_unref(bus);
-        pager_close();
-        polkit_agent_close();
-
-        strv_free(arg_property);
-        strv_free(arg_setenv);
-
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        return machinectl_main(argc, argv, bus);
 }
+
+DEFINE_MAIN_FUNCTION(run);