summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2022-04-01 10:02:29 +0100
committerNicholas Marriott <nicholas.marriott@gmail.com>2022-04-01 10:02:29 +0100
commitc837da602d63c1068b4bad51bc7a2994a07ec07c (patch)
treee00b414c5e917ec80d0aef4864a3e29ad232b680
parent639c0356204f97d861cff6f417d9e590e1786eba (diff)
parent87b248f3e86f7157baf69e5d9d458d1f2b4ceb7b (diff)
Merge branch 'master' into sixel-passthrough
-rw-r--r--CHANGES40
-rw-r--r--Makefile.am5
-rw-r--r--arguments.c16
-rw-r--r--client.c2
-rw-r--r--cmd-list-clients.c2
-rw-r--r--cmd-refresh-client.c39
-rw-r--r--cmd-resize-pane.c13
-rw-r--r--cmd-show-options.c7
-rw-r--r--cmd-split-window.c31
-rw-r--r--colour.c2
-rw-r--r--compat.h10
-rw-r--r--compat/getpeereid.c59
-rw-r--r--compat/systemd.c58
-rw-r--r--configure.ac43
-rw-r--r--format-draw.c6
-rw-r--r--format.c107
-rw-r--r--grid.c98
-rw-r--r--input-keys.c15
-rw-r--r--input.c56
-rw-r--r--job.c3
-rw-r--r--key-bindings.c2
-rw-r--r--key-string.c42
-rw-r--r--menu.c6
-rw-r--r--mode-tree.c12
-rw-r--r--notify.c63
-rw-r--r--options-table.c64
-rw-r--r--options.c6
-rw-r--r--osdep-netbsd.c3
-rw-r--r--osdep-openbsd.c1
-rw-r--r--popup.c17
-rw-r--r--proc.c11
-rw-r--r--resize.c3
-rw-r--r--screen-redraw.c99
-rw-r--r--screen-write.c10
-rw-r--r--server-client.c666
-rw-r--r--server-fn.c42
-rw-r--r--server.c12
-rw-r--r--session.c5
-rw-r--r--status.c6
-rw-r--r--tmux.191
-rw-r--r--tmux.h318
-rw-r--r--tty-features.c15
-rw-r--r--tty-keys.c37
-rw-r--r--tty-term.c1
-rw-r--r--tty.c73
-rw-r--r--window-copy.c21
-rw-r--r--window-customize.c4
-rw-r--r--window.c20
48 files changed, 1883 insertions, 379 deletions
diff --git a/CHANGES b/CHANGES
index d1dbb6ea..159ab905 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,45 @@
CHANGES FROM 3.2a TO 3.3
+* Add an option (pane-border-indicators) to select how the active pane is shown
+ on the pane border (colour, arrows or both).
+
+* Support underscore styles with capture-pane -e.
+
+* Make pane-border-format a pane option rather than window.
+
+* Respond to OSC 4 queries
+
+* Fix g/G keys in modes to do the same thing as copy mode (and vi).
+
+* Bump the time terminals have to respond to device attributes queries to three
+ seconds.
+
+* If automatic-rename is off, allow the rename escape sequence to set an empty
+ name.
+
+* Trim menu item text more intelligently.
+
+* Add cursor-style and cursor-colour options to set the default cursor style
+ and colour.
+
+* Accept some useful and non-conflicting emacs keys in vi normal mode at the
+ command prompt.
+
+* Add a format modifier (c) to force a colour to RGB.
+
+* Add -s and -S to display-popup to set styles, -b to set lines and -T to set
+ popup title. New popup-border-lines, popup-border-style and popup-style
+ options set the defaults.
+
+* Add -e flag to set an environment variable for a popup.
+
+* Make send-keys without arguments send the key it is bound to (if bound to a
+ key).
+
+* Try to leave terminal cursor at the right position even when tmux is drawing
+ its own cursor or selection (such as at the command prompt and in choose
+ mode) for people using screen readers and similar which can make use of it.
+
* Change so that {} is converted to tmux commands immediately when parsed. This
means it must contain valid tmux commands. For commands which expand %% and
%%%, this now only happens within string arguments. Use of nested aliases
diff --git a/Makefile.am b/Makefile.am
index 68494932..5bdd9d5f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -204,6 +204,11 @@ if NEED_FORKPTY
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
endif
+# Add compat file for systemd.
+if HAVE_SYSTEMD
+nodist_tmux_SOURCES += compat/systemd.c
+endif
+
# Add compat file for utf8proc.
if HAVE_UTF8PROC
nodist_tmux_SOURCES += compat/utf8proc.c
diff --git a/arguments.c b/arguments.c
index a27d8e0a..91c470e2 100644
--- a/arguments.c
+++ b/arguments.c
@@ -131,8 +131,9 @@ args_parse(const struct args_parse *parse, struct args_value *values,
u_int i;
enum args_parse_type type;
struct args_value *value, *new;
- u_char flag, argument;
+ u_char flag;
const char *found, *string, *s;
+ int optional_argument;
if (count == 0)
return (args_create());
@@ -169,18 +170,27 @@ args_parse(const struct args_parse *parse, struct args_value *values,
args_free(args);
return (NULL);
}
- argument = *++found;
- if (argument != ':') {
+ if (*++found != ':') {
log_debug("%s: -%c", __func__, flag);
args_set(args, flag, NULL);
continue;
}
+ if (*found == ':') {
+ optional_argument = 1;
+ found++;
+ }
new = xcalloc(1, sizeof *new);
if (*string != '\0') {
new->type = ARGS_STRING;
new->string = xstrdup(string);
} else {
if (i == count) {
+ if (optional_argument) {
+ log_debug("%s: -%c", __func__,
+ flag);
+ args_set(args, flag, NULL);
+ continue;
+ }
xasprintf(cause,
"-%c expects an argument",
flag);
diff --git a/client.c b/client.c
index 8ca08524..08708c21 100644
--- a/client.c
+++ b/client.c
@@ -531,7 +531,7 @@ client_signal(int sig)
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
- if (sig == SIGTERM)
+ if (sig == SIGTERM || sig == SIGHUP)
proc_exit(client_proc);
} else {
switch (sig) {
diff --git a/cmd-list-clients.c b/cmd-list-clients.c
index a5b7d147..53a99178 100644
--- a/cmd-list-clients.c
+++ b/cmd-list-clients.c
@@ -31,6 +31,8 @@
#define LIST_CLIENTS_TEMPLATE \
"#{client_name}: #{session_name} " \
"[#{client_width}x#{client_height} #{client_termname}] " \
+ "#{?#{!=:#{client_uid},#{uid}}," \
+ "[user #{?client_user,#{client_user},#{client_uid},}] ,}" \
"#{?client_flags,(,}#{client_flags}#{?client_flags,),}"
static enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmdq_item *);
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 821558ae..b2665ad9 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -34,7 +34,7 @@ const struct cmd_entry cmd_refresh_client_entry = {
.name = "refresh-client",
.alias = "refresh",
- .args = { "A:B:cC:Df:F:lLRSt:U", 0, 1, NULL },
+ .args = { "A:B:cC:Df:F:l::LRSt:U", 0, 1, NULL },
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
"[-C XxY] [-f flags] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
@@ -163,6 +163,37 @@ out:
}
static enum cmd_retval
+cmd_refresh_client_clipboard(struct cmd *self, struct cmdq_item *item)
+{
+ struct args *args = cmd_get_args(self);
+ struct client *tc = cmdq_get_target_client(item);
+ const char *p;
+ u_int i;
+ struct cmd_find_state fs;
+
+ p = args_get(args, 'l');
+ if (p == NULL) {
+ if (tc->flags & CLIENT_CLIPBOARDBUFFER)
+ return (CMD_RETURN_NORMAL);
+ tc->flags |= CLIENT_CLIPBOARDBUFFER;
+ } else {
+ if (cmd_find_target(&fs, item, p, CMD_FIND_PANE, 0) != 0)
+ return (CMD_RETURN_ERROR);
+ for (i = 0; i < tc->clipboard_npanes; i++) {
+ if (tc->clipboard_panes[i] == fs.wp->id)
+ break;
+ }
+ if (i != tc->clipboard_npanes)
+ return (CMD_RETURN_NORMAL);
+ tc->clipboard_panes = xreallocarray (tc->clipboard_panes,
+ tc->clipboard_npanes + 1, sizeof *tc->clipboard_panes);
+ tc->clipboard_panes[tc->clipboard_npanes++] = fs.wp->id;
+ }
+ tty_clipboard_query(&tc->tty);
+ return (CMD_RETURN_NORMAL);
+}
+
+static enum cmd_retval
cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
@@ -224,10 +255,8 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
- if (args_has(args, 'l')) {
- tty_putcode_ptr2(&tc->tty, TTYC_MS, "", "?");
- return (CMD_RETURN_NORMAL);
- }
+ if (args_has(args, 'l'))
+ return (cmd_refresh_client_clipboard(self, item));
if (args_has(args, 'F')) /* -F is an alias for -f */
server_client_set_flags(tc, args_get(args, 'F'));
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index 81744f72..c9439441 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -60,7 +60,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
const char *errstr;
char *cause;
u_int adjust;
- int x, y;
+ int x, y, status;
struct grid *gd = wp->base.grid;
if (args_has(args, 'T')) {
@@ -121,6 +121,17 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
free(cause);
return (CMD_RETURN_ERROR);
}
+ status = options_get_number(w->options, "pane-border-status");
+ switch (status) {
+ case PANE_STATUS_TOP:
+ if (y != INT_MAX && wp->yoff == 1)
+ y++;
+ break;
+ case PANE_STATUS_BOTTOM:
+ if (y != INT_MAX && wp->yoff + wp->sy == w->sy - 1)
+ y++;
+ break;
+ }
layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
}
diff --git a/cmd-show-options.c b/cmd-show-options.c
index 90226ad3..252a33c6 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -102,7 +102,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
name = options_match(argument, &idx, &ambiguous);
if (name == NULL) {
if (args_has(args, 'q'))
- goto fail;
+ goto out;
if (ambiguous)
cmdq_error(item, "ambiguous option: %s", argument);
else
@@ -113,7 +113,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
&cause);
if (scope == OPTIONS_TABLE_NONE) {
if (args_has(args, 'q'))
- goto fail;
+ goto out;
cmdq_error(item, "%s", cause);
free(cause);
goto fail;
@@ -128,11 +128,12 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
cmd_show_options_print(self, item, o, idx, parent);
else if (*name == '@') {
if (args_has(args, 'q'))
- goto fail;
+ goto out;
cmdq_error(item, "invalid option: %s", argument);
goto fail;
}
+out:
free(name);
free(argument);
return (CMD_RETURN_NORMAL);
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 888d4106..9947dfd3 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -60,6 +60,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct winlink *wl = target->wl;
+ struct window *w = wl->window;
struct window_pane *wp = target->wp, *new_wp;
enum layout_type type;
struct layout_cell *lc;
@@ -86,10 +87,17 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "percentage %s", errstr);
return (CMD_RETURN_ERROR);
}
- if (type == LAYOUT_TOPBOTTOM)
- size = (wp->sy * percentage) / 100;
- else
- size = (wp->sx * percentage) / 100;
+ if (args_has(args, 'f')) {
+ if (type == LAYOUT_TOPBOTTOM)
+ size = (w->sy * percentage) / 100;
+ else
+ size = (w->sx * percentage) / 100;
+ } else {
+ if (type == LAYOUT_TOPBOTTOM)
+ size = (wp->sy * percentage) / 100;
+ else
+ size = (wp->sx * percentage) / 100;
+ }
} else {
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (cause != NULL) {
@@ -105,10 +113,17 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
free(cause);
return (CMD_RETURN_ERROR);
}
- if (type == LAYOUT_TOPBOTTOM)
- size = (wp->sy * percentage) / 100;
- else
- size = (wp->sx * percentage) / 100;
+ if (args_has(args, 'f')) {
+ if (type == LAYOUT_TOPBOTTOM)
+ size = (w->sy * percentage) / 100;
+ else
+ size = (w->sx * percentage) / 100;
+ } else {
+ if (type == LAYOUT_TOPBOTTOM)
+ size = (wp->sy * percentage) / 100;
+ else
+ size = (wp->sx * percentage) / 100;
+ }
} else
size = -1;
diff --git a/colour.c b/colour.c
index 6ede25da..a282d182 100644
--- a/colour.c
+++ b/colour.c
@@ -128,7 +128,7 @@ colour_tostring(int c)
u_char r, g, b;
if (c == -1)
- return ("invalid");
+ return ("none");
if (c & COLOUR_FLAG_RGB) {
colour_split_rgb(c, &r, &g, &b);
diff --git a/compat.h b/compat.h
index 13334ad7..6eb97619 100644
--- a/compat.h
+++ b/compat.h
@@ -334,6 +334,11 @@ char *strndup(const char *, size_t);
void *memmem(const void *, size_t, const void *, size_t);
#endif
+#ifndef HAVE_GETPEEREID
+/* getpeereid.c */
+int getpeereid(int, uid_t *, gid_t *);
+#endif
+
#ifndef HAVE_DAEMON
/* daemon.c */
int daemon(int, int);
@@ -416,6 +421,11 @@ void *reallocarray(void *, size_t, size_t);
void *recallocarray(void *, size_t, size_t, size_t);
#endif
+#ifdef HAVE_SYSTEMD
+/* systemd.c */
+int systemd_create_socket(int, char **);
+#endif
+
#ifdef HAVE_UTF8PROC
/* utf8proc.c */
int utf8proc_wcwidth(wchar_t);
diff --git a/compat/getpeereid.c b/compat/getpeereid.c
new file mode 100644
index 00000000..5a593c07
--- /dev/null
+++ b/compat/getpeereid.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2022 Nicholas Marriott <nicholas.marriott@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
+
+#include "compat.h"
+
+int
+getpeereid(int s, uid_t *uid, gid_t *gid)
+{
+#ifdef HAVE_SO_PEERCRED
+ struct ucred uc;
+ int len = sizeof uc;
+
+ if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &uc, &len) == -1)
+ return (-1);
+ *uid = uc.uid;
+ *gid = uc.gid;
+ return (0);
+#elif defined(HAVE_GETPEERUCRED)
+int
+getpeereid(int s, uid_t *uid, gid_t *gid)
+{
+ ucred_t *ucred = NULL;
+
+ if (getpeerucred(s, &ucred) == -1)
+ return (-1);
+ if ((*uid = ucred_geteuid(ucred)) == -1)
+ return (-1);
+ if ((*gid = ucred_getrgid(ucred)) == -1)
+ return (-1);
+ ucred_free(ucred);
+ return (0);
+}
+#else
+ errno = EOPNOTSUPP;
+ return (-1);
+#endif
+}
diff --git a/compat/systemd.c b/compat/systemd.c
new file mode 100644
index 00000000..7317e43a
--- /dev/null
+++ b/compat/systemd.c
@@ -0,0 +1,58 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2022 Nicholas Marriott <nicholas.marriott@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <systemd/sd-daemon.h>
+
+#include "tmux.h"
+
+int
+systemd_create_socket(int flags, char **cause)
+{
+ int fds;
+ int fd;
+ struct sockaddr_un sa;
+ int addrlen = sizeof sa;
+
+ fds = sd_listen_fds(0);
+ if (fds > 1) { /* too many file descriptors */
+ errno = E2BIG;
+ goto fail;
+ }
+
+ if (fds == 1) { /* socket-activated */
+ fd = SD_LISTEN_FDS_START;
+ if (!sd_is_socket_unix(fd, SOCK_STREAM, 1, NULL, 0)) {
+ errno = EPFNOSUPPORT;
+ goto fail;
+ }
+ if (getsockname(fd, (struct sockaddr *)&sa, &addrlen) == -1)
+ goto fail;
+ socket_path = xstrdup(sa.sun_path);
+ return (fd);
+ }
+
+ return (server_create_socket(flags, cause));
+
+fail:
+ if (cause != NULL)
+ xasprintf(cause, "systemd socket error (%s)", strerror(errno));
+ return (-1);
+}
diff --git a/configure.ac b/configure.ac
index 26bd1a98..276f71c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,11 @@ AC_ARG_ENABLE(
AS_HELP_STRING(--enable-static, create a static build)
)
if test "x$enable_static" = xyes; then
+ case "$host_os" in
+ *darwin*)
+ AC_MSG_ERROR([static linking is not supported on macOS])
+ ;;
+ esac
test "x$PKG_CONFIG" != x && PKG_CONFIG="$PKG_CONFIG --static"
AM_LDFLAGS="-static $AM_LDFLAGS"
LDFLAGS="$AM_LDFLAGS $SAVED_LDFLAGS"
@@ -123,6 +128,7 @@ AC_CHECK_HEADERS([ \
sys/dir.h \
sys/ndir.h \
sys/tree.h \
+ ucred.h \
util.h \
])
@@ -141,7 +147,8 @@ AC_CHECK_FUNCS([ \
flock \
prctl \
proc_pidinfo \
- sysconf
+ getpeerucred \
+ sysconf \
])
# Check for functions with a compatibility implementation.
@@ -155,6 +162,7 @@ AC_REPLACE_FUNCS([ \
freezero \
getdtablecount \
getdtablesize \
+ getpeereid \
getline \
getprogname \
memmem \
@@ -382,6 +390,31 @@ if test "x$enable_utf8proc" = xyes; then
fi
AM_CONDITIONAL(HAVE_UTF8PROC, [test "x$enable_utf8proc" = xyes])
+# Check for systemd support.
+AC_ARG_ENABLE(
+ systemd,
+ AS_HELP_STRING(--enable-systemd, enable systemd integration)
+)
+if test x"$enable_systemd" = xyes; then
+ PKG_CHECK_MODULES(
+ SYSTEMD,
+ libsystemd,
+ [
+ AM_CPPFLAGS="$SYSTEMD_CFLAGS $AM_CPPFLAGS"
+ CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
+ LIBS="$SYSTEMD_LIBS $LIBS"
+ found_systemd=yes
+ ],
+ found_systemd=no
+ )
+ if test "x$found_systemd" = xyes; then
+ AC_DEFINE(HAVE_SYSTEMD)
+ else
+ AC_MSG_ERROR("systemd not found")
+ fi
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test "x$found_systemd" = xyes])
+
# Check for b64_ntop. If we have b64_ntop, we assume b64_pton as well.
AC_MSG_CHECKING(for b64_ntop)
AC_LINK_IFELSE([AC_LANG_PROGRAM(
@@ -679,6 +712,14 @@ AC_CHECK_DECL(
[#include <sys/prctl.h>]
)
+# Look for setsockopt(SO_PEERCRED).
+AC_CHECK_DECL(
+ SO_PEERCRED,
+ AC_DEFINE(HAVE_SO_PEERCRED),
+ ,
+ [#include <sys/socket.h>]
+)
+
# Look for fcntl(F_CLOSEM).
AC_CHECK_DECL(
F_CLOSEM,
diff --git a/format-draw.c b/format-draw.c
index 1110535f..1a7e60b3 100644
--- a/format-draw.c
+++ b/format-draw.c
@@ -1154,13 +1154,13 @@ format_trim_right(const char *expanded, u_int limit)
while (*cp != '\0') {
if (*cp == '#') {
end = format_leading_hashes(cp, &n, &leading_width);
+ copy_width = leading_width;
if (width <= skip) {
- if (skip - width >= leading_width)
+ if (skip - width >= copy_width)
copy_width = 0;
else
copy_width -= (skip - width);
- } else
- copy_width = leading_width;
+ }
if (copy_width != 0) {
if (n == 1)
*out++ = '#';
diff --git a/format.c b/format.c
index 2fc0961e..2e4bceb5 100644
--- a/format.c
+++ b/format.c
@@ -24,6 +24,7 @@
#include <fnmatch.h>
#include <libgen.h>
#include <math.h>
+#include <pwd.h>
#include <regex.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -1387,6 +1388,35 @@ format_cb_client_tty(struct format_tree *ft)
return (NULL);
}
+/* Callback for client_uid. */
+static void *
+format_cb_client_uid(struct format_tree *ft)
+{
+ uid_t uid;
+
+ if (ft->c != NULL) {
+ uid = proc_get_peer_uid(ft->c->peer);
+ if (uid != (uid_t)-1)
+ return (format_printf("%ld", (long)uid));
+ }
+ return (NULL);
+}
+
+/* Callback for client_user. */
+static void *
+format_cb_client_user(struct format_tree *ft)
+{
+ uid_t uid;
+ struct passwd *pw;
+
+ if (ft->c != NULL) {
+ uid = proc_get_peer_uid(ft->c->peer);
+ if (uid != (uid_t)-1 && (pw = getpwuid(uid)) != NULL)
+ return (xstrdup(pw->pw_name));
+ }
+ return (NULL);
+}
+
/* Callback for client_utf8. */
static void *
format_cb_client_utf8(struct format_tree *ft)
@@ -1650,6 +1680,13 @@ format_cb_mouse_y(struct format_tree *ft)
return (NULL);
}
+/* Callback for next_session_id. */
+static void *
+format_cb_next_session_id(__unused struct format_tree *ft)
+{
+ return (format_printf("$%u", next_session_id));
+}
+
/* Callback for origin_flag. */
static void *
format_cb_origin_flag(struct format_tree *ft)
@@ -1719,6 +1756,23 @@ format_cb_pane_dead(struct format_tree *ft)
return (NULL);
}
+/* Callback for pane_dead_signal. */
+static void *
+format_cb_pane_dead_signal(struct format_tree *ft)
+{
+ struct window_pane *wp = ft->wp;
+ const char *name;
+
+ if (wp != NULL) {
+ if ((wp->flags & PANE_STATUSREADY) && WIFSIGNALED(wp->status)) {
+ name = sig2name(WTERMSIG(wp->status));
+ return (format_printf("%s", name));
+ }
+ return (NULL);
+ }
+ return (NULL);
+}
+
/* Callback for pane_dead_status. */
static void *
format_cb_pane_dead_status(struct format_tree *ft)
@@ -1733,6 +1787,20 @@ format_cb_pane_dead_status(struct format_tree *ft)
return (NULL);
}
+/* Callback for pane_dead_time. */
+static void *
+format_cb_pane_dead_time(struct format_tree *ft)
+{
+ struct window_pane *wp = ft->wp;
+
+ if (wp != NULL) {
+ if (wp->flags & PANE_STATUSDRAWN)
+ return (&wp->dead_time);
+ return (NULL);
+ }
+ return (NULL);
+}
+
/* Callback for pane_format. */
static void *
format_cb_pane_format(struct format_tree *ft)
@@ -2514,6 +2582,24 @@ format_cb_tree_mode_format(__unused struct format_tree *ft)
return (xstrdup(window_tree_mode.default_format));
}
+/* Callback for uid. */
+static void *
+format_cb_uid(__unused struct format_tree *ft)
+{
+ return (format_printf("%ld", (long)getuid()));
+}
+
+/* Callback for user. */
+static void *
+format_cb_user(__unused struct format_tree *ft)
+{
+ struct passwd *pw;
+
+ if ((pw = getpwuid(getuid())) != NULL)
+ return (xstrdup(pw->pw_name));
+ return NULL;
+}
+
/* Format table type. */
enum format_table_type {
FORMAT_TABLE_STRING,
@@ -2620,6 +2706,12 @@ static const struct format_table_entry format_table[] = {
{ "client_tty", FORMAT_TABLE_STRING,
format_cb_client_tty
},
+ { "client_uid", FORMAT_TABLE_STRING,
+ format_cb_client_uid
+ },
+ { "client_user", FORMAT_TABLE_STRING,
+ format_cb_client_user
+ },
{ "client_utf8", FORMAT_TABLE_STRING,
format_cb_