std::string convert_and_ellipsize(std::string s, int len) { if (s.find('<') == 0) { int e = s.find('>'); std::stringstream ss; ss << "<span foreground=\"#" << font::color2hexa(font::markup2color(s.substr(1, e - 1))) << "\">"; ss << ellipsize(s.substr(e + 1), len); ss << "</span>"; return ss.str(); } else { return ellipsize(s, len); } }
static void centerstring (Rect r, Str255 s) { /* draw the string in the current font, size and style, centered inside the indicated rectangle. */ short rh = r.bottom - r.top; short rw = r.right - r.left; short h, v; FontInfo fi; GetFontInfo (&fi); ellipsize (s, rw); /*make sure it fits inside the rectangle, width-wise*/ h = r.left + ((rw - StringWidth (s)) / 2); v = r.top + ((rh - (fi.ascent + fi.descent)) / 2) + fi.ascent; MoveTo (h, v); ClipRect (&r); DrawString (s); } /*centerstring*/
static void log_accessible (EventLog *log, Accessible *accessible) { GtkTextTag *tag; GtkTextIter iter; char *text, *name, *descr, *short_descr; char *role_name, *ifaces; if (!accessible) { log_message (log, "<Null>"); return; } tag = gtk_text_buffer_create_tag (log->log_text, NULL, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); Accessible_ref (accessible); g_object_set_data_full (G_OBJECT (tag), "accessible", accessible, (GDestroyNotify) Accessible_unref ); ifaces = accessible_get_iface_string (accessible); role_name = Accessible_getRoleName (accessible); name = Accessible_getName (accessible); descr = Accessible_getDescription (accessible); short_descr = ellipsize (descr); /* FIXME: nice mangled printout of supported interfaces ? */ text = g_strdup_printf ("%s:%s:%s:%s", ifaces, role_name ? role_name : "--", name ? name : "--", short_descr ? short_descr : "--"); gtk_text_buffer_get_end_iter (log->log_text, &iter); gtk_text_buffer_insert_with_tags (log->log_text, &iter, text, -1, tag, NULL); g_free (text); g_free (short_descr); SPI_freeString (descr); SPI_freeString (name); SPI_freeString (role_name); g_free (ifaces); log_track_end (log); }
static int show_menu(char **x, unsigned n_columns, unsigned width, unsigned percentage) { unsigned n, per_column, i, j; unsigned break_lines, break_modulo; assert(n_columns > 0); n = strv_length(x); per_column = (n + n_columns - 1) / n_columns; break_lines = lines(); if (break_lines > 2) break_lines--; /* The first page gets two extra lines, since we want to show * a title */ break_modulo = break_lines; if (break_modulo > 3) break_modulo -= 3; for (i = 0; i < per_column; i++) { for (j = 0; j < n_columns; j ++) { _cleanup_free_ char *e = NULL; if (j * per_column + i >= n) break; e = ellipsize(x[j * per_column + i], width, percentage); if (!e) return log_oom(); printf("%4u) %-*s", j * per_column + i + 1, width, e); } putchar('\n'); /* on the first screen we reserve 2 extra lines for the title */ if (i % break_lines == break_modulo) { if (!press_any_key()) return 0; } } return 0; }
int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) { static const char status_indent[] = " "; /* "[" STATUS "] " */ _cleanup_free_ char *s = NULL; _cleanup_close_ int fd = -1; struct iovec iovec[6] = {}; int n = 0; static bool prev_ephemeral; assert(format); /* This is independent of logging, as status messages are * optional and go exclusively to the console. */ if (vasprintf(&s, format, ap) < 0) return log_oom(); fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; if (ellipse) { char *e; size_t emax, sl; int c; c = fd_columns(fd); if (c <= 0) c = 80; sl = status ? sizeof(status_indent)-1 : 0; emax = c - sl - 1; if (emax < 3) emax = 3; e = ellipsize(s, emax, 50); if (e) { free(s); s = e; } } if (prev_ephemeral) IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE); prev_ephemeral = ephemeral; if (status) { if (!isempty(status)) { IOVEC_SET_STRING(iovec[n++], "["); IOVEC_SET_STRING(iovec[n++], status); IOVEC_SET_STRING(iovec[n++], "] "); } else IOVEC_SET_STRING(iovec[n++], status_indent); } IOVEC_SET_STRING(iovec[n++], s); if (!ephemeral) IOVEC_SET_STRING(iovec[n++], "\n"); if (writev(fd, iovec, n) < 0) return -errno; return 0; }
static void display(Hashmap *a) { Iterator i; Group *g; Group **array; signed path_columns; unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 3; /* 3 for ellipsize() to work properly */ char buffer[MAX3(21, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)]; assert(a); if (!terminal_is_dumb()) fputs(ANSI_HOME_CLEAR, stdout); array = alloca(sizeof(Group*) * hashmap_size(a)); HASHMAP_FOREACH(g, a, i) if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) array[n++] = g; qsort_safe(array, n, sizeof(Group*), group_compare); /* Find the longest names in one run */ for (j = 0; j < n; j++) { unsigned cputlen, pathtlen; format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0); cputlen = strlen(buffer); maxtcpu = MAX(maxtcpu, cputlen); pathtlen = strlen(array[j]->path); maxtpath = MAX(maxtpath, pathtlen); } if (arg_cpu_type == CPU_PERCENT) xsprintf(buffer, "%6s", "%CPU"); else xsprintf(buffer, "%*s", maxtcpu, "CPU Time"); rows = lines(); if (rows <= 10) rows = 10; if (on_tty()) { const char *on, *off; path_columns = columns() - 36 - strlen(buffer); if (path_columns < 10) path_columns = 10; on = ansi_highlight_underline(); off = ansi_underline(); printf("%s%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s%s\n", ansi_underline(), arg_order == ORDER_PATH ? on : "", path_columns, "Control Group", arg_order == ORDER_PATH ? off : "", arg_order == ORDER_TASKS ? on : "", arg_count == COUNT_PIDS ? "Tasks" : arg_count == COUNT_USERSPACE_PROCESSES ? "Procs" : "Proc+", arg_order == ORDER_TASKS ? off : "", arg_order == ORDER_CPU ? on : "", buffer, arg_order == ORDER_CPU ? off : "", arg_order == ORDER_MEMORY ? on : "", "Memory", arg_order == ORDER_MEMORY ? off : "", arg_order == ORDER_IO ? on : "", "Input/s", arg_order == ORDER_IO ? off : "", arg_order == ORDER_IO ? on : "", "Output/s", arg_order == ORDER_IO ? off : "", ansi_normal()); } else path_columns = maxtpath; for (j = 0; j < n; j++) { _cleanup_free_ char *ellipsized = NULL; const char *path; if (on_tty() && j + 6 > rows) break; g = array[j]; path = isempty(g->path) ? "/" : g->path; ellipsized = ellipsize(path, path_columns, 33); printf("%-*s", path_columns, ellipsized ?: path); if (g->n_tasks_valid) printf(" %7" PRIu64, g->n_tasks); else fputs(" -", stdout); if (arg_cpu_type == CPU_PERCENT) { if (g->cpu_valid) printf(" %6.1f", g->cpu_fraction*100); else fputs(" -", stdout); } else printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->memory_valid, g->memory)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_input_bps)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_output_bps)); putchar('\n'); } }
static int display(Hashmap *a) { Iterator i; Group *g; Group **array; signed path_columns; unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 0; char buffer[MAX3(21, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)]; assert(a); /* Set cursor to top left corner and clear screen */ if (on_tty()) fputs("\033[H" "\033[2J", stdout); array = alloca(sizeof(Group*) * hashmap_size(a)); HASHMAP_FOREACH(g, a, i) if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) array[n++] = g; qsort_safe(array, n, sizeof(Group*), group_compare); /* Find the longest names in one run */ for (j = 0; j < n; j++) { unsigned cputlen, pathtlen; format_timespan(buffer, sizeof(buffer), (nsec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0); cputlen = strlen(buffer); maxtcpu = MAX(maxtcpu, cputlen); pathtlen = strlen(array[j]->path); maxtpath = MAX(maxtpath, pathtlen); } if (arg_cpu_type == CPU_PERCENT) snprintf(buffer, sizeof(buffer), "%6s", "%CPU"); else snprintf(buffer, sizeof(buffer), "%*s", maxtcpu, "CPU Time"); rows = lines(); if (rows <= 10) rows = 10; if (on_tty()) { path_columns = columns() - 36 - strlen(buffer); if (path_columns < 10) path_columns = 10; printf("%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s\n\n", arg_order == ORDER_PATH ? ON : "", path_columns, "Path", arg_order == ORDER_PATH ? OFF : "", arg_order == ORDER_TASKS ? ON : "", "Tasks", arg_order == ORDER_TASKS ? OFF : "", arg_order == ORDER_CPU ? ON : "", buffer, arg_order == ORDER_CPU ? OFF : "", arg_order == ORDER_MEMORY ? ON : "", "Memory", arg_order == ORDER_MEMORY ? OFF : "", arg_order == ORDER_IO ? ON : "", "Input/s", arg_order == ORDER_IO ? OFF : "", arg_order == ORDER_IO ? ON : "", "Output/s", arg_order == ORDER_IO ? OFF : ""); } else path_columns = maxtpath; for (j = 0; j < n; j++) { char *p; if (on_tty() && j + 5 > rows) break; g = array[j]; p = ellipsize(g->path, path_columns, 33); printf("%-*s", path_columns, p ? p : g->path); free(p); if (g->n_tasks_valid) printf(" %7u", g->n_tasks); else fputs(" -", stdout); if (arg_cpu_type == CPU_PERCENT) { if (g->cpu_valid) printf(" %6.1f", g->cpu_fraction*100); else fputs(" -", stdout); } else printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (nsec_t) (g->cpu_usage / NSEC_PER_USEC), 0)); if (g->memory_valid) printf(" %8s", format_bytes(buffer, sizeof(buffer), g->memory)); else fputs(" -", stdout); if (g->io_valid) { printf(" %8s", format_bytes(buffer, sizeof(buffer), g->io_input_bps)); printf(" %8s", format_bytes(buffer, sizeof(buffer), g->io_output_bps)); } else fputs(" - -", stdout); putchar('\n'); } return 0; }
char* optdoc(char* dst, size_t dst_size, const char* app_name, const option* options, size_t num_options, const char* loose_parameters) { *dst = '\0'; char* cur = dst; int w = snprintf(cur, dst_size, "%s [options] ", app_name); if (w == -1) return nullptr; cur += w; dst_size -= w; const option* oend = options + num_options; for (const option* o = options; o < oend; o++) { w = snprintf(cur, dst_size, "-%c%s%s ", o->abbrev, o->argname ? " " : "", o->argname ? o->argname : ""); if (w == -1) return nullptr; cur += w; dst_size -= w; } if (loose_parameters && *loose_parameters) { w = snprintf(cur, dst_size, "%s", loose_parameters); cur += w; dst_size -= w; } w = snprintf(cur, dst_size, "\n\n"); if (w == -1) return nullptr; cur += w; dst_size -= w; size_t max_len_fullname = 0; size_t max_len_arg_name = 0; for (const option* o = options; o < oend && dst_size > 0; o++) { max_len_fullname = __max(max_len_fullname, strlen(o->fullname ? o->fullname : "")); max_len_arg_name = __max(max_len_arg_name, strlen(o->argname ? o->argname : "")); } static const size_t MaxLen = 80; const size_t descStartCol = 3 + 1 + max_len_fullname + 5 + max_len_arg_name + 4; for (const option* o = options; o < oend && dst_size > 0; o++) { char fullname[64]; *fullname = '\0'; if (o->fullname) snprintf(fullname, " [--%s]", o->fullname); const char* odesc = o->desc ? o->desc : ""; size_t newline = strcspn(odesc, oNEWLINE); char descline[128]; if (newline > sizeof(descline)) return nullptr; strlcpy(descline, odesc); bool do_more_lines = descline[newline] != '\0'; descline[newline] = '\0'; w = snprintf(cur, dst_size, " -%c%- *s %- *s : %s\n" , o->abbrev , max_len_fullname + 5 , fullname , max_len_arg_name , o->argname ? o->argname : "" , descline); if (w == -1) return nullptr; cur += w; dst_size -= w; while (do_more_lines) { odesc += newline + 1; newline = strcspn(odesc, oNEWLINE); if (newline > sizeof(descline)) return nullptr; strlcpy(descline, odesc); do_more_lines = descline[newline] != '\0'; descline[newline] = '\0'; w = snprintf(cur, dst_size, "% *s%s\n" , descStartCol , " " , descline); if (w == -1) return dst; cur += w; dst_size -= w; } } ellipsize(dst, dst_size); return dst; }
static int show_sysfs_one( struct udev *udev, const char *seat, struct udev_list_entry **item, const char *sub, const char *prefix, unsigned n_columns) { assert(udev); assert(seat); assert(item); assert(prefix); while (*item) { struct udev_list_entry *next, *lookahead; struct udev_device *d; const char *sn, *name, *sysfs, *subsystem, *sysname; char *l, *k; bool is_master; sysfs = udev_list_entry_get_name(*item); if (!path_startswith(sysfs, sub)) return 0; d = udev_device_new_from_syspath(udev, sysfs); if (!d) { *item = udev_list_entry_get_next(*item); continue; } sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(sn)) sn = "seat0"; /* Explicitly also check for tag 'seat' here */ if (!streq(seat, sn) || !udev_device_has_tag(d, "seat")) { udev_device_unref(d); *item = udev_list_entry_get_next(*item); continue; } is_master = udev_device_has_tag(d, "seat-master"); name = udev_device_get_sysattr_value(d, "name"); if (!name) name = udev_device_get_sysattr_value(d, "id"); subsystem = udev_device_get_subsystem(d); sysname = udev_device_get_sysname(d); /* Look if there's more coming after this */ lookahead = next = udev_list_entry_get_next(*item); while (lookahead) { const char *lookahead_sysfs; lookahead_sysfs = udev_list_entry_get_name(lookahead); if (path_startswith(lookahead_sysfs, sub) && !path_startswith(lookahead_sysfs, sysfs)) { struct udev_device *lookahead_d; lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs); if (lookahead_d) { const char *lookahead_sn; bool found; lookahead_sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(lookahead_sn)) lookahead_sn = "seat0"; found = streq(seat, lookahead_sn) && udev_device_has_tag(lookahead_d, "seat"); udev_device_unref(lookahead_d); if (found) break; } } lookahead = udev_list_entry_get_next(lookahead); } k = ellipsize(sysfs, n_columns, 20); printf("%s%s%s\n", prefix, draw_special_char(lookahead ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT), k ? k : sysfs); free(k); if (asprintf(&l, "%s%s:%s%s%s%s", is_master ? "[MASTER] " : "", subsystem, sysname, name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) { udev_device_unref(d); return -ENOMEM; } k = ellipsize(l, n_columns, 70); printf("%s%s%s\n", prefix, lookahead ? draw_special_char(DRAW_TREE_VERT) : " ", k ? k : l); free(k); free(l); *item = next; if (*item) { char *p; p = strappend(prefix, lookahead ? draw_special_char(DRAW_TREE_VERT) : " "); show_sysfs_one(udev, seat, item, sysfs, p ? p : prefix, n_columns - 2); free(p); } udev_device_unref(d); } return 0; }
static int print_inhibitors(DBusConnection *bus, DBusError *error) { DBusMessage *m, *reply; unsigned n = 0; DBusMessageIter iter, sub, sub2; int r; assert(bus); m = dbus_message_new_method_call( "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ListInhibitors"); if (!m) return -ENOMEM; reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error); if (!reply) { r = -EIO; goto finish; } if (!dbus_message_iter_init(reply, &iter)) { r = -ENOMEM; goto finish; } if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { r = -EIO; goto finish; } dbus_message_iter_recurse(&iter, &sub); printf("%-21s %-20s %-20s %-5s %6s %6s\n", "WHAT", "WHO", "WHY", "MODE", "UID", "PID"); while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) { const char *what, *who, *why, *mode; char *ewho, *ewhy; dbus_uint32_t uid, pid; if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) { r = -EIO; goto finish; } dbus_message_iter_recurse(&sub, &sub2); if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) { r = -EIO; goto finish; } ewho = ellipsize(who, 20, 66); ewhy = ellipsize(why, 20, 66); printf("%-21s %-20s %-20s %-5s %6lu %6lu\n", what, ewho ? ewho : who, ewhy ? ewhy : why, mode, (unsigned long) uid, (unsigned long) pid); free(ewho); free(ewhy); dbus_message_iter_next(&sub); n++; } printf("\n%u inhibitors listed.\n", n); r = 0; finish: if (m) dbus_message_unref(m); if (reply) dbus_message_unref(reply); return r; }
int status_vprintf(const char *status, ShowStatusFlags flags, const char *format, va_list ap) { static const char status_indent[] = " "; /* "[" STATUS "] " */ _cleanup_free_ char *s = NULL; _cleanup_close_ int fd = -1; struct iovec iovec[7] = {}; int n = 0; static bool prev_ephemeral; assert(format); /* This is independent of logging, as status messages are * optional and go exclusively to the console. */ if (vasprintf(&s, format, ap) < 0) return log_oom(); /* Before you ask: yes, on purpose we open/close the console for each status line we write individually. This * is a good strategy to avoid PID 1 getting killed by the kernel's SAK concept (it doesn't fix this entirely, * but minimizes the time window the kernel might end up killing PID 1 due to SAK). It also makes things easier * for us so that we don't have to recover from hangups and suchlike triggered on the console. */ fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; if (FLAGS_SET(flags, SHOW_STATUS_ELLIPSIZE)) { char *e; size_t emax, sl; int c; c = fd_columns(fd); if (c <= 0) c = 80; sl = status ? sizeof(status_indent)-1 : 0; emax = c - sl - 1; if (emax < 3) emax = 3; e = ellipsize(s, emax, 50); if (e) free_and_replace(s, e); } if (prev_ephemeral) iovec[n++] = IOVEC_MAKE_STRING(ANSI_REVERSE_LINEFEED "\r" ANSI_ERASE_TO_END_OF_LINE); if (status) { if (!isempty(status)) { iovec[n++] = IOVEC_MAKE_STRING("["); iovec[n++] = IOVEC_MAKE_STRING(status); iovec[n++] = IOVEC_MAKE_STRING("] "); } else iovec[n++] = IOVEC_MAKE_STRING(status_indent); } iovec[n++] = IOVEC_MAKE_STRING(s); iovec[n++] = IOVEC_MAKE_STRING("\n"); if (prev_ephemeral && !FLAGS_SET(flags, SHOW_STATUS_EPHEMERAL)) iovec[n++] = IOVEC_MAKE_STRING(ANSI_ERASE_TO_END_OF_LINE); prev_ephemeral = FLAGS_SET(flags, SHOW_STATUS_EPHEMERAL) ; if (writev(fd, iovec, n) < 0) return -errno; return 0; }
static void test_one(const char *p) { _cleanup_free_ char *t; t = ellipsize(p, columns(), 70); puts(t); }