mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Support OSC 52 ? to read the top buffer inside tmux, also add
refresh-client -l to get the clipboard outside tmux. GitHub issue 1477.
This commit is contained in:
		@@ -33,8 +33,8 @@ const struct cmd_entry cmd_refresh_client_entry = {
 | 
			
		||||
	.name = "refresh-client",
 | 
			
		||||
	.alias = "refresh",
 | 
			
		||||
 | 
			
		||||
	.args = { "cC:DLRSt:U", 0, 1 },
 | 
			
		||||
	.usage = "[-cDLRSU] [-C size] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
 | 
			
		||||
	.args = { "cC:DlLRSt:U", 0, 1 },
 | 
			
		||||
	.usage = "[-cDlLRSU] [-C size] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
 | 
			
		||||
 | 
			
		||||
	.flags = CMD_AFTERHOOK,
 | 
			
		||||
	.exec = cmd_refresh_client_exec
 | 
			
		||||
@@ -104,7 +104,10 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
		return (CMD_RETURN_NORMAL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 'C')) {
 | 
			
		||||
	if (args_has(args, 'l')) {
 | 
			
		||||
		if (c->session != NULL)
 | 
			
		||||
			tty_putcode_ptr2(&c->tty, TTYC_MS, "", "?");
 | 
			
		||||
	} else if (args_has(args, 'C')) {
 | 
			
		||||
		if ((size = args_get(args, 'C')) == NULL) {
 | 
			
		||||
			cmdq_error(item, "missing size");
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										118
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								input.c
									
									
									
									
									
								
							@@ -93,6 +93,10 @@ struct input_ctx {
 | 
			
		||||
	u_char		       *input_buf;
 | 
			
		||||
	size_t			input_len;
 | 
			
		||||
	size_t			input_space;
 | 
			
		||||
	enum {
 | 
			
		||||
		INPUT_END_ST,
 | 
			
		||||
		INPUT_END_BEL
 | 
			
		||||
	}			input_end;
 | 
			
		||||
 | 
			
		||||
	struct input_param	param_list[24];
 | 
			
		||||
	u_int			param_list_len;
 | 
			
		||||
@@ -126,11 +130,11 @@ static void	input_set_state(struct window_pane *,
 | 
			
		||||
		    const struct input_transition *);
 | 
			
		||||
static void	input_reset_cell(struct input_ctx *);
 | 
			
		||||
 | 
			
		||||
static void	input_osc_4(struct window_pane *, const char *);
 | 
			
		||||
static void	input_osc_10(struct window_pane *, const char *);
 | 
			
		||||
static void	input_osc_11(struct window_pane *, const char *);
 | 
			
		||||
static void	input_osc_52(struct window_pane *, const char *);
 | 
			
		||||
static void	input_osc_104(struct window_pane *, const char *);
 | 
			
		||||
static void	input_osc_4(struct input_ctx *, const char *);
 | 
			
		||||
static void	input_osc_10(struct input_ctx *, const char *);
 | 
			
		||||
static void	input_osc_11(struct input_ctx *, const char *);
 | 
			
		||||
static void	input_osc_52(struct input_ctx *, const char *);
 | 
			
		||||
static void	input_osc_104(struct input_ctx *, const char *);
 | 
			
		||||
 | 
			
		||||
/* Transition entry/exit handlers. */
 | 
			
		||||
static void	input_clear(struct input_ctx *);
 | 
			
		||||
@@ -161,6 +165,7 @@ static void	input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
 | 
			
		||||
static void	input_csi_dispatch_sgr(struct input_ctx *);
 | 
			
		||||
static int	input_dcs_dispatch(struct input_ctx *);
 | 
			
		||||
static int	input_top_bit_set(struct input_ctx *);
 | 
			
		||||
static int	input_end_bel(struct input_ctx *);
 | 
			
		||||
 | 
			
		||||
/* Command table comparison function. */
 | 
			
		||||
static int	input_table_compare(const void *, const void *);
 | 
			
		||||
@@ -487,7 +492,7 @@ static const struct input_transition input_state_esc_enter_table[] = {
 | 
			
		||||
	{ -1, -1, NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* esc_interm state table. */
 | 
			
		||||
/* esc_intermediate state table. */
 | 
			
		||||
static const struct input_transition input_state_esc_intermediate_table[] = {
 | 
			
		||||
	INPUT_STATE_ANYWHERE,
 | 
			
		||||
 | 
			
		||||
@@ -602,7 +607,7 @@ static const struct input_transition input_state_dcs_parameter_table[] = {
 | 
			
		||||
	{ -1, -1, NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* dcs_interm state table. */
 | 
			
		||||
/* dcs_intermediate state table. */
 | 
			
		||||
static const struct input_transition input_state_dcs_intermediate_table[] = {
 | 
			
		||||
	INPUT_STATE_ANYWHERE,
 | 
			
		||||
 | 
			
		||||
@@ -655,12 +660,12 @@ static const struct input_transition input_state_dcs_ignore_table[] = {
 | 
			
		||||
static const struct input_transition input_state_osc_string_table[] = {
 | 
			
		||||
	INPUT_STATE_ANYWHERE,
 | 
			
		||||
 | 
			
		||||
	{ 0x00, 0x06, NULL,	    NULL },
 | 
			
		||||
	{ 0x07, 0x07, NULL,	    &input_state_ground },
 | 
			
		||||
	{ 0x08, 0x17, NULL,	    NULL },
 | 
			
		||||
	{ 0x19, 0x19, NULL,	    NULL },
 | 
			
		||||
	{ 0x1c, 0x1f, NULL,	    NULL },
 | 
			
		||||
	{ 0x20, 0xff, input_input,  NULL },
 | 
			
		||||
	{ 0x00, 0x06, NULL,	     NULL },
 | 
			
		||||
	{ 0x07, 0x07, input_end_bel, &input_state_ground },
 | 
			
		||||
	{ 0x08, 0x17, NULL,	     NULL },
 | 
			
		||||
	{ 0x19, 0x19, NULL,	     NULL },
 | 
			
		||||
	{ 0x1c, 0x1f, NULL,	     NULL },
 | 
			
		||||
	{ 0x20, 0xff, input_input,   NULL },
 | 
			
		||||
 | 
			
		||||
	{ -1, -1, NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
@@ -993,8 +998,8 @@ input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
 | 
			
		||||
static void
 | 
			
		||||
input_reply(struct input_ctx *ictx, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list	ap;
 | 
			
		||||
	char   *reply;
 | 
			
		||||
	va_list	 ap;
 | 
			
		||||
	char	*reply;
 | 
			
		||||
 | 
			
		||||
	va_start(ap, fmt);
 | 
			
		||||
	xvasprintf(&reply, fmt, ap);
 | 
			
		||||
@@ -1019,6 +1024,8 @@ input_clear(struct input_ctx *ictx)
 | 
			
		||||
	*ictx->input_buf = '\0';
 | 
			
		||||
	ictx->input_len = 0;
 | 
			
		||||
 | 
			
		||||
	ictx->input_end = INPUT_END_ST;
 | 
			
		||||
 | 
			
		||||
	ictx->flags &= ~INPUT_DISCARD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2046,6 +2053,17 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* End of input with BEL. */
 | 
			
		||||
static int
 | 
			
		||||
input_end_bel(struct input_ctx *ictx)
 | 
			
		||||
{
 | 
			
		||||
	log_debug("%s", __func__);
 | 
			
		||||
 | 
			
		||||
	ictx->input_end = INPUT_END_BEL;
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* DCS string started. */
 | 
			
		||||
static void
 | 
			
		||||
input_enter_dcs(struct input_ctx *ictx)
 | 
			
		||||
@@ -2102,7 +2120,8 @@ input_exit_osc(struct input_ctx *ictx)
 | 
			
		||||
	if (ictx->input_len < 1 || *p < '0' || *p > '9')
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: \"%s\"", __func__, p);
 | 
			
		||||
	log_debug("%s: \"%s\" (end %s)", __func__, p,
 | 
			
		||||
	    ictx->input_end == INPUT_END_ST ? "ST" : "BEL");
 | 
			
		||||
 | 
			
		||||
	option = 0;
 | 
			
		||||
	while (*p >= '0' && *p <= '9')
 | 
			
		||||
@@ -2119,23 +2138,23 @@ input_exit_osc(struct input_ctx *ictx)
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case 4:
 | 
			
		||||
		input_osc_4(ictx->wp, p);
 | 
			
		||||
		input_osc_4(ictx, p);
 | 
			
		||||
		break;
 | 
			
		||||
	case 10:
 | 
			
		||||
		input_osc_10(ictx->wp, p);
 | 
			
		||||
		input_osc_10(ictx, p);
 | 
			
		||||
		break;
 | 
			
		||||
	case 11:
 | 
			
		||||
		input_osc_11(ictx->wp, p);
 | 
			
		||||
		input_osc_11(ictx, p);
 | 
			
		||||
		break;
 | 
			
		||||
	case 12:
 | 
			
		||||
		if (utf8_isvalid(p) && *p != '?') /* ? is colour request */
 | 
			
		||||
			screen_set_cursor_colour(ictx->ctx.s, p);
 | 
			
		||||
		break;
 | 
			
		||||
	case 52:
 | 
			
		||||
		input_osc_52(ictx->wp, p);
 | 
			
		||||
		input_osc_52(ictx, p);
 | 
			
		||||
		break;
 | 
			
		||||
	case 104:
 | 
			
		||||
		input_osc_104(ictx->wp, p);
 | 
			
		||||
		input_osc_104(ictx, p);
 | 
			
		||||
		break;
 | 
			
		||||
	case 112:
 | 
			
		||||
		if (*p == '\0') /* no arguments allowed */
 | 
			
		||||
@@ -2237,11 +2256,12 @@ input_top_bit_set(struct input_ctx *ictx)
 | 
			
		||||
 | 
			
		||||
/* Handle the OSC 4 sequence for setting (multiple) palette entries. */
 | 
			
		||||
static void
 | 
			
		||||
input_osc_4(struct window_pane *wp, const char *p)
 | 
			
		||||
input_osc_4(struct input_ctx *ictx, const char *p)
 | 
			
		||||
{
 | 
			
		||||
	char	*copy, *s, *next = NULL;
 | 
			
		||||
	long	 idx;
 | 
			
		||||
	u_int	 r, g, b;
 | 
			
		||||
	struct window_pane	*wp = ictx->wp;
 | 
			
		||||
	char			*copy, *s, *next = NULL;
 | 
			
		||||
	long	 		idx;
 | 
			
		||||
	u_int			 r, g, b;
 | 
			
		||||
 | 
			
		||||
	copy = s = xstrdup(p);
 | 
			
		||||
	while (s != NULL && *s != '\0') {
 | 
			
		||||
@@ -2271,9 +2291,10 @@ bad:
 | 
			
		||||
 | 
			
		||||
/* Handle the OSC 10 sequence for setting foreground colour. */
 | 
			
		||||
static void
 | 
			
		||||
input_osc_10(struct window_pane *wp, const char *p)
 | 
			
		||||
input_osc_10(struct input_ctx *ictx, const char *p)
 | 
			
		||||
{
 | 
			
		||||
	u_int	 r, g, b;
 | 
			
		||||
	struct window_pane	*wp = ictx->wp;
 | 
			
		||||
	u_int			 r, g, b;
 | 
			
		||||
 | 
			
		||||
	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
 | 
			
		||||
	    goto bad;
 | 
			
		||||
@@ -2289,9 +2310,10 @@ bad:
 | 
			
		||||
 | 
			
		||||
/* Handle the OSC 11 sequence for setting background colour. */
 | 
			
		||||
static void
 | 
			
		||||
input_osc_11(struct window_pane *wp, const char *p)
 | 
			
		||||
input_osc_11(struct input_ctx *ictx, const char *p)
 | 
			
		||||
{
 | 
			
		||||
	u_int	 r, g, b;
 | 
			
		||||
	struct window_pane	*wp = ictx->wp;
 | 
			
		||||
	u_int			 r, g, b;
 | 
			
		||||
 | 
			
		||||
	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
 | 
			
		||||
	    goto bad;
 | 
			
		||||
@@ -2307,13 +2329,16 @@ bad:
 | 
			
		||||
 | 
			
		||||
/* Handle the OSC 52 sequence for setting the clipboard. */
 | 
			
		||||
static void
 | 
			
		||||
input_osc_52(struct window_pane *wp, const char *p)
 | 
			
		||||
input_osc_52(struct input_ctx *ictx, const char *p)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp = ictx->wp;
 | 
			
		||||
	char			*end;
 | 
			
		||||
	const char		*buf;
 | 
			
		||||
	size_t			 len;
 | 
			
		||||
	u_char			*out;
 | 
			
		||||
	int			 outlen, state;
 | 
			
		||||
	struct screen_write_ctx	 ctx;
 | 
			
		||||
	struct paste_buffer	*pb;
 | 
			
		||||
 | 
			
		||||
	state = options_get_number(global_options, "set-clipboard");
 | 
			
		||||
	if (state != 2)
 | 
			
		||||
@@ -2324,6 +2349,32 @@ input_osc_52(struct window_pane *wp, const char *p)
 | 
			
		||||
	end++;
 | 
			
		||||
	if (*end == '\0')
 | 
			
		||||
		return;
 | 
			
		||||
	log_debug("%s: %s", __func__, end);
 | 
			
		||||
 | 
			
		||||
	if (strcmp(end, "?") == 0) {
 | 
			
		||||
		if ((pb = paste_get_top(NULL)) != NULL) {
 | 
			
		||||
			buf = paste_buffer_data(pb, &len);
 | 
			
		||||
			outlen = 4 * ((len + 2) / 3) + 1;
 | 
			
		||||
			out = xmalloc(outlen);
 | 
			
		||||
			if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
 | 
			
		||||
				abort();
 | 
			
		||||
				free(out);
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			outlen = 0;
 | 
			
		||||
			out = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		bufferevent_write(wp->event, "\033]52;;", 6);
 | 
			
		||||
		if (outlen != 0)
 | 
			
		||||
			bufferevent_write(wp->event, out, outlen);
 | 
			
		||||
		if (ictx->input_end == INPUT_END_BEL)
 | 
			
		||||
			bufferevent_write(wp->event, "\007", 1);
 | 
			
		||||
		else
 | 
			
		||||
			bufferevent_write(wp->event, "\033\\", 2);
 | 
			
		||||
		free(out);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	len = (strlen(end) / 4) * 3;
 | 
			
		||||
	if (len == 0)
 | 
			
		||||
@@ -2345,10 +2396,11 @@ input_osc_52(struct window_pane *wp, const char *p)
 | 
			
		||||
 | 
			
		||||
/* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
 | 
			
		||||
static void
 | 
			
		||||
input_osc_104(struct window_pane *wp, const char *p)
 | 
			
		||||
input_osc_104(struct input_ctx *ictx, const char *p)
 | 
			
		||||
{
 | 
			
		||||
	char	*copy, *s;
 | 
			
		||||
	long	idx;
 | 
			
		||||
	struct window_pane	*wp = ictx->wp;
 | 
			
		||||
	char			*copy, *s;
 | 
			
		||||
	long			idx;
 | 
			
		||||
 | 
			
		||||
	if (*p == '\0') {
 | 
			
		||||
		window_pane_reset_palette(wp);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								tmux.1
									
									
									
									
									
								
							@@ -930,7 +930,7 @@ is used, the
 | 
			
		||||
.Ic update-environment
 | 
			
		||||
option will not be applied.
 | 
			
		||||
.It Xo Ic refresh-client
 | 
			
		||||
.Op Fl cDLRSU
 | 
			
		||||
.Op Fl cDlLRSU
 | 
			
		||||
.Op Fl C Ar XxY
 | 
			
		||||
.Op Fl t Ar target-client
 | 
			
		||||
.Op Ar adjustment
 | 
			
		||||
@@ -975,6 +975,10 @@ it.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl C
 | 
			
		||||
sets the width and height of a control client.
 | 
			
		||||
.Fl l
 | 
			
		||||
requests the clipboard from the client using the
 | 
			
		||||
.Xr xterm 1
 | 
			
		||||
escape sequence and stores it in a new paste buffer.
 | 
			
		||||
.It Xo Ic rename-session
 | 
			
		||||
.Op Fl t Ar target-session
 | 
			
		||||
.Ar new-name
 | 
			
		||||
@@ -3996,7 +4000,7 @@ option.
 | 
			
		||||
.El
 | 
			
		||||
.Pp
 | 
			
		||||
When a pane is first created, its title is the hostname.
 | 
			
		||||
A pane's title can be set via the OSC title setting sequence, for example:
 | 
			
		||||
A pane's title can be set via the title setting escape sequence, for example:
 | 
			
		||||
.Bd -literal -offset indent
 | 
			
		||||
$ printf '\e033]2;My Title\e033\e\e'
 | 
			
		||||
.Ed
 | 
			
		||||
@@ -4550,7 +4554,7 @@ Indicate that the terminal supports the
 | 
			
		||||
.Ql direct colour
 | 
			
		||||
RGB escape sequence (for example, \ee[38;2;255;255;255m).
 | 
			
		||||
.Pp
 | 
			
		||||
If supported, this is used for the OSC initialize colour escape sequence (which
 | 
			
		||||
If supported, this is used for the initialize colour escape sequence (which
 | 
			
		||||
may be enabled by adding the
 | 
			
		||||
.Ql initc
 | 
			
		||||
and
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								tty-keys.c
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								tty-keys.c
									
									
									
									
									
								
							@@ -19,7 +19,10 @@
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <resolv.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <termios.h>
 | 
			
		||||
@@ -44,6 +47,8 @@ static int	tty_keys_next1(struct tty *, const char *, size_t, key_code *,
 | 
			
		||||
		    size_t *, int);
 | 
			
		||||
static void	tty_keys_callback(int, short, void *);
 | 
			
		||||
static int	tty_keys_mouse(struct tty *, const char *, size_t, size_t *);
 | 
			
		||||
static int	tty_keys_clipboard(struct tty *, const char *, size_t,
 | 
			
		||||
		    size_t *);
 | 
			
		||||
static int	tty_keys_device_attributes(struct tty *, const char *, size_t,
 | 
			
		||||
		    size_t *);
 | 
			
		||||
 | 
			
		||||
@@ -571,6 +576,17 @@ tty_keys_next(struct tty *tty)
 | 
			
		||||
		return (0);
 | 
			
		||||
	log_debug("%s: keys are %zu (%.*s)", c->name, len, (int)len, buf);
 | 
			
		||||
 | 
			
		||||
	/* Is this a clipboard response? */
 | 
			
		||||
	switch (tty_keys_clipboard(tty, buf, len, &size)) {
 | 
			
		||||
	case 0:		/* yes */
 | 
			
		||||
		key = KEYC_UNKNOWN;
 | 
			
		||||
		goto complete_key;
 | 
			
		||||
	case -1:	/* no, or not valid */
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:		/* partial */
 | 
			
		||||
		goto partial_key;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is this a device attributes response? */
 | 
			
		||||
	switch (tty_keys_device_attributes(tty, buf, len, &size)) {
 | 
			
		||||
	case 0:		/* yes */
 | 
			
		||||
@@ -871,6 +887,93 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Handle OSC 52 clipboard input. Returns 0 for success, -1 for failure, 1 for
 | 
			
		||||
 * partial.
 | 
			
		||||
 */
 | 
			
		||||
static int
 | 
			
		||||
tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
 | 
			
		||||
    size_t *size)
 | 
			
		||||
{
 | 
			
		||||
	size_t	 end, terminator, needed;
 | 
			
		||||
	char	*copy, *out;
 | 
			
		||||
	int	 outlen;
 | 
			
		||||
 | 
			
		||||
	*size = 0;
 | 
			
		||||
 | 
			
		||||
	/* First three bytes are always \033]52;. */
 | 
			
		||||
	if (buf[0] != '\033')
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (len == 1)
 | 
			
		||||
		return (1);
 | 
			
		||||
	if (buf[1] != ']')
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (len == 2)
 | 
			
		||||
		return (1);
 | 
			
		||||
	if (buf[2] != '5')
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (len == 3)
 | 
			
		||||
		return (1);
 | 
			
		||||
	if (buf[3] != '2')
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (len == 4)
 | 
			
		||||
		return (1);
 | 
			
		||||
	if (buf[4] != ';')
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (len == 5)
 | 
			
		||||
		return (1);
 | 
			
		||||
 | 
			
		||||
	/* Find the terminator if any. */
 | 
			
		||||
	for (end = 5; end < len; end++) {
 | 
			
		||||
		if (buf[end] == '\007') {
 | 
			
		||||
			terminator = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (end > 5 && buf[end - 1] == '\033' && buf[end] == '\\') {
 | 
			
		||||
			terminator = 2;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (end == len)
 | 
			
		||||
		return (1);
 | 
			
		||||
	*size = end + terminator;
 | 
			
		||||
 | 
			
		||||
	/* Skip the initial part. */
 | 
			
		||||
	buf += 5;
 | 
			
		||||
	end -= 5;
 | 
			
		||||
 | 
			
		||||
	/* Get the second argument. */
 | 
			
		||||
	while (end != 0 && *buf != ';') {
 | 
			
		||||
		buf++;
 | 
			
		||||
		end--;
 | 
			
		||||
	}
 | 
			
		||||
	if (end == 0 || end == 1)
 | 
			
		||||
		return (0);
 | 
			
		||||
	buf++;
 | 
			
		||||
	end--;
 | 
			
		||||
 | 
			
		||||
	/* It has to be a string so copy it. */
 | 
			
		||||
	copy = xmalloc(end + 1);
 | 
			
		||||
	memcpy(copy, buf, end);
 | 
			
		||||
	copy[end] = '\0';
 | 
			
		||||
 | 
			
		||||
	/* Convert from base64. */
 | 
			
		||||
	needed = (end / 4) * 3;
 | 
			
		||||
	out = xmalloc(needed);
 | 
			
		||||
	if ((outlen = b64_pton(copy, out, len)) == -1) {
 | 
			
		||||
		free(out);
 | 
			
		||||
		free(copy);
 | 
			
		||||
		return (0);
 | 
			
		||||
	}
 | 
			
		||||
	free(copy);
 | 
			
		||||
 | 
			
		||||
	/* Create a new paste buffer. */
 | 
			
		||||
	log_debug("%s: %.*s", __func__, outlen, out);
 | 
			
		||||
	paste_add(out, outlen);
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Handle device attributes input. Returns 0 for success, -1 for failure, 1 for
 | 
			
		||||
 * partial.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user