X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsystemctl%2Fsystemctl.c;h=af7ecd7af15d8e89f7e8e375c7b2ec58afa47a0c;hb=75add28aa17678fbf5b10947027efe7ac75d113d;hp=fe71085d423d6660a8276551f3b87529461c2d55;hpb=2fa4092c2829dd14e50c430ae2f23551d23c6c1d;p=elogind.git diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index fe71085d4..af7ecd7af 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -895,13 +895,84 @@ static int list_dependencies(DBusConnection *bus, char **args) { return list_dependencies_one(bus, u, 0, NULL, 0); } +struct job_info { + uint32_t id; + char *name, *type, *state; +}; + +static void list_jobs_print(struct job_info* jobs, size_t n) { + size_t i; + struct job_info *j; + const char *on, *off; + bool shorten = false; + + assert(n == 0 || jobs); + + if (n == 0) { + on = ansi_highlight_green(true); + off = ansi_highlight_green(false); + + printf("%sNo jobs running.%s\n", on, off); + return; + } + + pager_open_if_enabled(); + + { + /* JOB UNIT TYPE STATE */ + unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5; + + for (i = 0, j = jobs; i < n; i++, j++) { + assert(j->name && j->type && j->state); + l0 = MAX(l0, decimal_str_max(j->id)); + l1 = MAX(l1, strlen(j->name)); + l2 = MAX(l2, strlen(j->type)); + l3 = MAX(l3, strlen(j->state)); + } + + if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) { + l1 = MAX(33u, columns() - l0 - l2 - l3 - 3); + shorten = true; + } + + if (on_tty()) + printf("%*s %-*s %-*s %-*s\n", + l0, "JOB", + l1, "UNIT", + l2, "TYPE", + l3, "STATE"); + + for (i = 0, j = jobs; i < n; i++, j++) { + char _cleanup_free_ *e = NULL; + + if (streq(j->state, "running")) { + on = ansi_highlight(true); + off = ansi_highlight(false); + } else + on = off = ""; + + e = shorten ? ellipsize(j->name, l1, 33) : NULL; + printf("%*u %s%-*s%s %-*s %s%-*s%s\n", + l0, j->id, + on, l1, e ? e : j->name, off, + l2, j->type, + on, l3, j->state, off); + } + } + + on = ansi_highlight(true); + off = ansi_highlight(false); + + if (on_tty()) + printf("\n%s%zu jobs listed%s.\n", on, n, off); +} + static int list_jobs(DBusConnection *bus, char **args) { _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; DBusMessageIter iter, sub, sub2; - unsigned k = 0; int r; - - pager_open_if_enabled(); + struct job_info *jobs = NULL; + size_t size = 0, used = 0; r = bus_method_call_with_reply( bus, @@ -924,13 +995,9 @@ static int list_jobs(DBusConnection *bus, char **args) { dbus_message_iter_recurse(&iter, &sub); - if (on_tty()) - printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE"); - while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) { const char *name, *type, *state, *job_path, *unit_path; uint32_t id; - char _cleanup_free_ *e = NULL; if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) { log_error("Failed to parse reply."); @@ -946,19 +1013,37 @@ static int list_jobs(DBusConnection *bus, char **args) { bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) { log_error("Failed to parse reply."); - return -EIO; + r = -EIO; + goto finish; } - e = arg_full ? NULL : ellipsize(name, 25, 33); - printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state); + if (!greedy_realloc((void**) &jobs, &size, + sizeof(struct job_info) * (used + 1))) { + r = log_oom(); + goto finish; + } - k++; + jobs[used++] = (struct job_info) { id, + strdup(name), + strdup(type), + strdup(state) }; + if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) { + r = log_oom(); + goto finish; + } dbus_message_iter_next(&sub); } - if (on_tty()) - printf("\n%u jobs listed.\n", k); + list_jobs_print(jobs, used); + + finish: + while (used--) { + free(jobs[used].name); + free(jobs[used].type); + free(jobs[used].state); + } + free(jobs); return 0; } @@ -1193,14 +1278,11 @@ static int enable_wait_for_jobs(DBusConnection *bus) { static int wait_for_jobs(DBusConnection *bus, Set *s) { int r = 0; - WaitData d; + WaitData d = { .set = s }; assert(bus); assert(s); - zero(d); - d.set = s; - if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) return log_oom(); @@ -2225,6 +2307,8 @@ typedef struct UnitStatusInfo { const char *source_path; const char *default_control_group; + char **dropin_paths; + const char *load_error; const char *result; @@ -2331,6 +2415,34 @@ static void print_status_info(UnitStatusInfo *i) { printf(" %*s: %s%s%s\n", maxlen, "Loaded", on, strna(i->load_state), off); + if (!strv_isempty(i->dropin_paths)) { + char ** dropin; + char * dir = NULL; + bool last = false; + + STRV_FOREACH(dropin, i->dropin_paths) { + if (! dir || last) { + printf(" %*s ", maxlen, dir ? "" : "Drop-In:"); + + free(dir); + + if (path_get_parent(*dropin, &dir) < 0) { + log_oom(); + return; + } + + printf("%s\n %*s %s", dir, maxlen, "", + draw_special_char(DRAW_TREE_RIGHT)); + } + + last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir)); + + printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", "); + } + + free(dir); + } + ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state; if (streq_ptr(i->active_state, "failed")) { @@ -2387,10 +2499,10 @@ static void print_status_info(UnitStatusInfo *i) { printf(" %*s: %s\n", maxlen, "What", i->what); STRV_FOREACH(t, i->documentation) - printf(" %*s: %s\n", maxlen, t == i->documentation ? "Docs" : "", *t); + printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t); STRV_FOREACH_PAIR(t, t2, i->listen) - printf(" %*s%s: %s\n", maxlen - (int)strlen(*t), "Listen", *t, *t2); + printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t); if (i->accept) printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections); @@ -2494,10 +2606,13 @@ static void print_status_info(UnitStatusInfo *i) { if (arg_transport != TRANSPORT_SSH) { unsigned k = 0; pid_t extra[2]; + char prefix[maxlen + 4]; + memset(prefix, ' ', sizeof(prefix) - 1); + prefix[sizeof(prefix) - 1] = '\0'; c = columns(); - if (c > 18) - c -= 18; + if (c > sizeof(prefix) - 1) + c -= sizeof(prefix) - 1; else c = 0; @@ -2507,7 +2622,8 @@ static void print_status_info(UnitStatusInfo *i) { if (i->control_pid > 0) extra[k++] = i->control_pid; - show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags); + show_cgroup_and_extra_by_spec(i->default_control_group, prefix, + c, false, extra, k, flags); } } @@ -2767,6 +2883,11 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn return 0; + } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) { + int r = bus_parse_strv_iter(iter, &i->dropin_paths); + if (r < 0) + return r; + } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "Documentation")) { @@ -2982,9 +3103,8 @@ static int print_property(const char *name, DBusMessageIter *iter) { dbus_message_iter_recurse(iter, &sub); while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) { - ExecStatusInfo info; + ExecStatusInfo info = {}; - zero(info); if (exec_status_info_deserialize(&sub, &info) >= 0) { char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX]; char _cleanup_free_ *t; @@ -3031,14 +3151,12 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo const char *interface = ""; int r; DBusMessageIter iter, sub, sub2, sub3; - UnitStatusInfo info; + UnitStatusInfo info = {}; ExecStatusInfo *p; assert(path); assert(new_line); - zero(info); - r = bus_method_call_with_reply( bus, "org.freedesktop.systemd1", @@ -3102,6 +3220,7 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo } strv_free(info.documentation); + strv_free(info.dropin_paths); strv_free(info.listen); if (!streq_ptr(info.active_state, "active") && @@ -3614,7 +3733,7 @@ static int enable_sysv_units(char **args) { #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG) const char *verb = args[0]; unsigned f = 1, t = 1; - LookupPaths paths; + LookupPaths paths = {}; if (arg_scope != UNIT_FILE_SYSTEM) return 0; @@ -3627,7 +3746,6 @@ static int enable_sysv_units(char **args) { /* Processes all SysV units, and reshuffles the array so that * afterwards only the native units remain */ - zero(paths); r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL); if (r < 0) return r; @@ -4676,7 +4794,7 @@ static int parse_time_spec(const char *t, usec_t *_u) { } else { char *e = NULL; long hour, minute; - struct tm tm; + struct tm tm = {}; time_t s; usec_t n; @@ -4692,7 +4810,6 @@ static int parse_time_spec(const char *t, usec_t *_u) { n = now(CLOCK_REALTIME); s = (time_t) (n / USEC_PER_SEC); - zero(tm); assert_se(localtime_r(&s, &tm)); tm.tm_hour = (int) hour; @@ -5094,7 +5211,7 @@ finish: } static int talk_initctl(void) { - struct init_request request = {0}; + struct init_request request = {}; int r; int _cleanup_close_ fd = -1; char rl; @@ -5299,41 +5416,38 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) { int _cleanup_close_ fd; - struct msghdr msghdr; - struct iovec iovec[2]; - union sockaddr_union sockaddr; - struct sd_shutdown_command c; + struct sd_shutdown_command c = { + .usec = t, + .mode = mode, + .dry_run = dry_run, + .warn_wall = warn, + }; + union sockaddr_union sockaddr = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/shutdownd", + }; + struct iovec iovec[2] = { + {.iov_base = (char*) &c, + .iov_len = offsetof(struct sd_shutdown_command, wall_message), + } + }; + struct msghdr msghdr = { + .msg_name = &sockaddr, + .msg_namelen = offsetof(struct sockaddr_un, sun_path) + + sizeof("/run/systemd/shutdownd") - 1, + .msg_iov = iovec, + .msg_iovlen = 1, + }; fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (fd < 0) return -errno; - zero(c); - c.usec = t; - c.mode = mode; - c.dry_run = dry_run; - c.warn_wall = warn; - - zero(sockaddr); - sockaddr.sa.sa_family = AF_UNIX; - strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path)); - - zero(msghdr); - msghdr.msg_name = &sockaddr; - msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1; - - zero(iovec); - iovec[0].iov_base = (char*) &c; - iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message); - - if (isempty(message)) - msghdr.msg_iovlen = 1; - else { + if (!isempty(message)) { iovec[1].iov_base = (char*) message; iovec[1].iov_len = strlen(message); - msghdr.msg_iovlen = 2; + msghdr.msg_iovlen++; } - msghdr.msg_iov = iovec; if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) return -errno;