GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/cmd-capture-pane.c Lines: 0 107 0.0 %
Date: 2017-11-07 Branches: 0 70 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: cmd-capture-pane.c,v 1.44 2017/04/22 10:22:39 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
21
#include <stdlib.h>
22
#include <string.h>
23
24
#include "tmux.h"
25
26
/*
27
 * Write the entire contents of a pane to a buffer or stdout.
28
 */
29
30
static enum cmd_retval	cmd_capture_pane_exec(struct cmd *, struct cmdq_item *);
31
32
static char	*cmd_capture_pane_append(char *, size_t *, char *, size_t);
33
static char	*cmd_capture_pane_pending(struct args *, struct window_pane *,
34
		     size_t *);
35
static char	*cmd_capture_pane_history(struct args *, struct cmdq_item *,
36
		     struct window_pane *, size_t *);
37
38
const struct cmd_entry cmd_capture_pane_entry = {
39
	.name = "capture-pane",
40
	.alias = "capturep",
41
42
	.args = { "ab:CeE:JpPqS:t:", 0, 0 },
43
	.usage = "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] "
44
		 "[-S start-line]" CMD_TARGET_PANE_USAGE,
45
46
	.target = { 't', CMD_FIND_PANE, 0 },
47
48
	.flags = CMD_AFTERHOOK,
49
	.exec = cmd_capture_pane_exec
50
};
51
52
const struct cmd_entry cmd_clear_history_entry = {
53
	.name = "clear-history",
54
	.alias = "clearhist",
55
56
	.args = { "t:", 0, 0 },
57
	.usage = CMD_TARGET_PANE_USAGE,
58
59
	.target = { 't', CMD_FIND_PANE, 0 },
60
61
	.flags = CMD_AFTERHOOK,
62
	.exec = cmd_capture_pane_exec
63
};
64
65
static char *
66
cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
67
{
68
	buf = xrealloc(buf, *len + linelen + 1);
69
	memcpy(buf + *len, line, linelen);
70
	*len += linelen;
71
	return (buf);
72
}
73
74
static char *
75
cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
76
    size_t *len)
77
{
78
	struct evbuffer	*pending;
79
	char		*buf, *line, tmp[5];
80
	size_t		 linelen;
81
	u_int		 i;
82
83
	pending = input_pending(wp);
84
	if (pending == NULL)
85
		return (xstrdup(""));
86
87
	line = EVBUFFER_DATA(pending);
88
	linelen = EVBUFFER_LENGTH(pending);
89
90
	buf = xstrdup("");
91
	if (args_has(args, 'C')) {
92
		for (i = 0; i < linelen; i++) {
93
			if (line[i] >= ' ' && line[i] != '\\') {
94
				tmp[0] = line[i];
95
				tmp[1] = '\0';
96
			} else
97
				xsnprintf(tmp, sizeof tmp, "\\%03hho", line[i]);
98
			buf = cmd_capture_pane_append(buf, len, tmp,
99
			    strlen(tmp));
100
		}
101
	} else
102
		buf = cmd_capture_pane_append(buf, len, line, linelen);
103
	return (buf);
104
}
105
106
static char *
107
cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
108
    struct window_pane *wp, size_t *len)
109
{
110
	struct grid		*gd;
111
	const struct grid_line	*gl;
112
	struct grid_cell	*gc = NULL;
113
	int			 n, with_codes, escape_c0, join_lines;
114
	u_int			 i, sx, top, bottom, tmp;
115
	char			*cause, *buf, *line;
116
	const char		*Sflag, *Eflag;
117
	size_t			 linelen;
118
119
	sx = screen_size_x(&wp->base);
120
	if (args_has(args, 'a')) {
121
		gd = wp->saved_grid;
122
		if (gd == NULL) {
123
			if (!args_has(args, 'q')) {
124
				cmdq_error(item, "no alternate screen");
125
				return (NULL);
126
			}
127
			return (xstrdup(""));
128
		}
129
	} else
130
		gd = wp->base.grid;
131
132
	Sflag = args_get(args, 'S');
133
	if (Sflag != NULL && strcmp(Sflag, "-") == 0)
134
		top = 0;
135
	else {
136
		n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
137
		if (cause != NULL) {
138
			top = gd->hsize;
139
			free(cause);
140
		} else if (n < 0 && (u_int) -n > gd->hsize)
141
			top = 0;
142
		else
143
			top = gd->hsize + n;
144
		if (top > gd->hsize + gd->sy - 1)
145
			top = gd->hsize + gd->sy - 1;
146
	}
147
148
	Eflag = args_get(args, 'E');
149
	if (Eflag != NULL && strcmp(Eflag, "-") == 0)
150
		bottom = gd->hsize + gd->sy - 1;
151
	else {
152
		n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
153
		if (cause != NULL) {
154
			bottom = gd->hsize + gd->sy - 1;
155
			free(cause);
156
		} else if (n < 0 && (u_int) -n > gd->hsize)
157
			bottom = 0;
158
		else
159
			bottom = gd->hsize + n;
160
		if (bottom > gd->hsize + gd->sy - 1)
161
			bottom = gd->hsize + gd->sy - 1;
162
	}
163
164
	if (bottom < top) {
165
		tmp = bottom;
166
		bottom = top;
167
		top = tmp;
168
	}
169
170
	with_codes = args_has(args, 'e');
171
	escape_c0 = args_has(args, 'C');
172
	join_lines = args_has(args, 'J');
173
174
	buf = NULL;
175
	for (i = top; i <= bottom; i++) {
176
		line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
177
		    escape_c0, !join_lines);
178
		linelen = strlen(line);
179
180
		buf = cmd_capture_pane_append(buf, len, line, linelen);
181
182
		gl = grid_peek_line(gd, i);
183
		if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED))
184
			buf[(*len)++] = '\n';
185
186
		free(line);
187
	}
188
	return (buf);
189
}
190
191
static enum cmd_retval
192
cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
193
{
194
	struct args		*args = self->args;
195
	struct client		*c;
196
	struct window_pane	*wp = item->target.wp;
197
	char			*buf, *cause;
198
	const char		*bufname;
199
	size_t			 len;
200
201
	if (self->entry == &cmd_clear_history_entry) {
202
		if (wp->mode == &window_copy_mode)
203
			window_pane_reset_mode(wp);
204
		grid_clear_history(wp->base.grid);
205
		return (CMD_RETURN_NORMAL);
206
	}
207
208
	len = 0;
209
	if (args_has(args, 'P'))
210
		buf = cmd_capture_pane_pending(args, wp, &len);
211
	else
212
		buf = cmd_capture_pane_history(args, item, wp, &len);
213
	if (buf == NULL)
214
		return (CMD_RETURN_ERROR);
215
216
	if (args_has(args, 'p')) {
217
		c = item->client;
218
		if (c == NULL ||
219
		    (c->session != NULL && !(c->flags & CLIENT_CONTROL))) {
220
			cmdq_error(item, "can't write to stdout");
221
			free(buf);
222
			return (CMD_RETURN_ERROR);
223
		}
224
		evbuffer_add(c->stdout_data, buf, len);
225
		free(buf);
226
		if (args_has(args, 'P') && len > 0)
227
		    evbuffer_add(c->stdout_data, "\n", 1);
228
		server_client_push_stdout(c);
229
	} else {
230
		bufname = NULL;
231
		if (args_has(args, 'b'))
232
			bufname = args_get(args, 'b');
233
234
		if (paste_set(buf, len, bufname, &cause) != 0) {
235
			cmdq_error(item, "%s", cause);
236
			free(cause);
237
			free(buf);
238
			return (CMD_RETURN_ERROR);
239
		}
240
	}
241
242
	return (CMD_RETURN_NORMAL);
243
}