pager_open(false);
}
+typedef struct MachineInfo {
+ const char *name;
+ const char *class;
+ const char *service;
+} MachineInfo;
+
+static int compare_machine_info(const void *a, const void *b) {
+ const MachineInfo *x = a, *y = b;
+
+ return strcmp(x->name, y->name);
+}
+
static int list_machines(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE");
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_free_ MachineInfo *machines = NULL;
const char *name, *class, *service, *object;
+ size_t n_machines = 0, n_allocated = 0, j;
sd_bus *bus = userdata;
- unsigned k = 0;
int r;
assert(bus);
return r;
}
- if (arg_legend)
- printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
-
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
if (r < 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
- printf("%-32s %-9s %-16s\n", name, class, service);
+ size_t l;
- k++;
+ if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1))
+ return log_oom();
+
+ machines[n_machines].name = name;
+ machines[n_machines].class = class;
+ machines[n_machines].service = service;
+
+ l = strlen(name);
+ if (l > max_name)
+ max_name = l;
+
+ l = strlen(class);
+ if (l > max_class)
+ max_class = l;
+
+ l = strlen(service);
+ if (l > max_service)
+ max_service = l;
+
+ n_machines ++;
}
if (r < 0)
return bus_log_parse_error(r);
if (r < 0)
return bus_log_parse_error(r);
+ qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info);
+
if (arg_legend)
- printf("\n%u machines listed.\n", k);
+ printf("%-*s %-*s %-*s\n",
+ (int) max_name, "MACHINE",
+ (int) max_class, "CLASS",
+ (int) max_service, "SERVICE");
+
+ for (j = 0; j < n_machines; j++)
+ printf("%-*s %-*s %-*s\n",
+ (int) max_name, machines[j].name,
+ (int) max_class, machines[j].class,
+ (int) max_service, machines[j].service);
+
+ if (arg_legend)
+ printf("\n%zu machines listed.\n", n_machines);
return 0;
}
(int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime)));
}
- if (r < 0)
- return bus_log_parse_error(r);
-
-
if (arg_legend)
printf("\n%zu images listed.\n", n_images);
putchar('\n');
}
- if (i->path)
+ if (i->type)
printf("\t Type: %s\n", i->type);
if (i->path)
return r;
}
+static int on_machine_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ PTYForward ** forward = (PTYForward**) userdata;
+ int r;
+
+ assert(bus);
+ assert(m);
+ assert(forward);
+
+ if (*forward) {
+ /* If the forwarder is already initialized, tell it to
+ * exit on the next vhangup(), so that we still flush
+ * out what might be queued and exit then. */
+
+ r = pty_forward_set_ignore_vhangup(*forward, false);
+ if (r >= 0)
+ return 0;
+
+ log_error_errno(r, "Failed to set ignore_vhangup flag: %m");
+ }
+
+ /* On error, or when the forwarder is not initialized yet, quit immediately */
+ sd_event_exit(sd_bus_get_event(bus), EXIT_FAILURE);
+ return 0;
+}
+
static int login_machine(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
_cleanup_event_unref_ sd_event *event = NULL;
int master = -1, r, ret = 0;
sd_bus *bus = userdata;
- const char *pty;
+ const char *pty, *match;
sigset_t mask;
char last_char = 0;
+ bool machine_died;
assert(bus);
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
+ match = strappenda("type='signal',"
+ "sender='org.freedesktop.machine1',"
+ "path='/org/freedesktop/machine1',",
+ "interface='org.freedesktop.machine1.Manager',"
+ "member='MachineRemoved',"
+ "arg0='",
+ argv[1],
+ "'");
+
+ r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add machine removal match: %m");
+
r = sd_bus_message_new_method_call(bus,
&m,
"org.freedesktop.machine1",
sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1);
assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
- log_info("Connected to container %s. Press ^] three times within 1s to exit session.", argv[1]);
+ log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", argv[1]);
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
- pty_forward_last_char(forward, &last_char);
+ pty_forward_get_last_char(forward, &last_char);
+ machine_died = pty_forward_get_ignore_vhangup(forward) == 0;
forward = pty_forward_free(forward);
if (last_char != '\n')
fputc('\n', stdout);
- log_info("Connection to container %s terminated.", argv[1]);
+ if (machine_died)
+ log_info("Machine %s terminated.", argv[1]);
+ else
+ log_info("Connection to machine %s terminated.", argv[1]);
sd_event_get_exit_code(event, &ret);
return ret;