summaryrefslogtreecommitdiff
path: root/src/basic/terminal-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-04-19 17:48:53 +0200
committerLennart Poettering <lennart@poettering.net>2018-04-19 18:04:26 +0200
commit23b27b39d2a3a002ad827a2e8a9872a51495d797 (patch)
tree41a12d6cad4dcd8e647b1a262f0cc70aebf1f359 /src/basic/terminal-util.c
parent2c75088094a1c3b0d743145ba224d078025eb5bc (diff)
downloadsystemd-23b27b39d2a3a002ad827a2e8a9872a51495d797.tar.gz
terminal: add internal API to format URLs for display in capable terminals
Newer terminals (in particular gnome-terminal) understand special escape sequence for formatting clickable links. Let's support that to make our tool output more clickable where that's appropriate. For details see this: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda The one big issue is that 'less' currently doesn't grok this, and doesn't ignore sequence like regular terminal implementations do if they don't support it. Hence for now, let's disable URL output if a pager is used. We should revisit that though as soon as less added support for it and enough time passed for it to enter various distributions.
Diffstat (limited to 'src/basic/terminal-util.c')
-rw-r--r--src/basic/terminal-util.c105
1 files changed, 99 insertions, 6 deletions
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index f0405e3c3a..3166145b33 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -8,21 +8,22 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <linux/kd.h>
+#include <linux/tiocl.h>
+#include <linux/vt.h>
+#include <poll.h>
+#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sysmacros.h>
#include <sys/time.h>
-#include <linux/kd.h>
-#include <linux/tiocl.h>
-#include <linux/vt.h>
-#include <poll.h>
-#include <signal.h>
-#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <termios.h>
#include <unistd.h>
@@ -34,6 +35,7 @@
#include "io-util.h"
#include "log.h"
#include "macro.h"
+#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
@@ -1269,3 +1271,94 @@ int vt_reset_keyboard(int fd) {
return 0;
}
+
+static bool urlify_enabled(void) {
+ static int cached_urlify_enabled = -1;
+
+ /* Unfortunately 'less' doesn't support links like this yet 😭, hence let's disable this as long as there's a
+ * pager in effect. Let's drop this check as soon as less got fixed a and enough time passed so that it's safe
+ * to assume that a link-enabled 'less' version has hit most installations. */
+
+ if (cached_urlify_enabled < 0) {
+ int val;
+
+ val = getenv_bool("SYSTEMD_URLIFY");
+ if (val >= 0)
+ cached_urlify_enabled = val;
+ else
+ cached_urlify_enabled = colors_enabled() && !pager_have();
+ }
+
+ return cached_urlify_enabled;
+}
+
+int terminal_urlify(const char *url, const char *text, char **ret) {
+ char *n;
+
+ assert(url);
+
+ /* Takes an URL and a pretty string and formats it as clickable link for the terminal. See
+ * https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda for details. */
+
+ if (isempty(text))
+ text = url;
+
+ if (urlify_enabled())
+ n = strjoin("\x1B]8;;", url, "\a", text, "\x1B]8;;\a");
+ else
+ n = strdup(text);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
+}
+
+int terminal_urlify_path(const char *path, const char *text, char **ret) {
+ _cleanup_free_ char *absolute = NULL;
+ struct utsname u;
+ const char *url;
+ int r;
+
+ assert(path);
+
+ /* Much like terminal_urlify() above, but takes a file system path as input, and turns it into a properl
+ * file:// URL first. */
+
+ if (isempty(path))
+ return -EINVAL;
+
+ if (isempty(text))
+ text = path;
+
+ if (!urlify_enabled()) {
+ char *n;
+
+ n = strdup(text);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
+ }
+
+ if (uname(&u) < 0)
+ return -errno;
+
+ if (!path_is_absolute(path)) {
+ r = path_make_absolute_cwd(path, &absolute);
+ if (r < 0)
+ return r;
+
+ path = absolute;
+ }
+
+ /* As suggested by https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda, let's include the local
+ * hostname here. Note that we don't use gethostname_malloc() or gethostname_strict() since we are interested
+ * in the raw string the kernel has set, whatever it may be, under the assumption that terminals are not overly
+ * careful with validating the strings either. */
+
+ url = strjoina("file://", u.nodename, path);
+
+ return terminal_urlify(url, text, ret);
+}