cmd-save-buffer.c revision 1.14
1/* $OpenBSD: cmd-save-buffer.c,v 1.14 2012/05/21 18:27:42 nicm Exp $ */
2
3/*
4 * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
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#include <sys/stat.h>
21
22#include <errno.h>
23#include <string.h>
24
25#include "tmux.h"
26
27/*
28 * Saves a paste buffer to a file.
29 */
30
31int	cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
32
33const struct cmd_entry cmd_save_buffer_entry = {
34	"save-buffer", "saveb",
35	"ab:", 1, 1,
36	"[-a] " CMD_BUFFER_USAGE " path",
37	0,
38	NULL,
39	NULL,
40	cmd_save_buffer_exec
41};
42
43int
44cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
45{
46	struct args		*args = self->args;
47	struct client		*c = ctx->cmdclient;
48	struct session          *s;
49	struct paste_buffer	*pb;
50	const char		*path, *newpath, *wd;
51	char			*cause;
52	int			 buffer;
53	mode_t			 mask;
54	FILE			*f;
55
56	if (!args_has(args, 'b')) {
57		if ((pb = paste_get_top(&global_buffers)) == NULL) {
58			ctx->error(ctx, "no buffers");
59			return (-1);
60		}
61	} else {
62		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
63		if (cause != NULL) {
64			ctx->error(ctx, "buffer %s", cause);
65			xfree(cause);
66			return (-1);
67		}
68
69		pb = paste_get_index(&global_buffers, buffer);
70		if (pb == NULL) {
71			ctx->error(ctx, "no buffer %d", buffer);
72			return (-1);
73		}
74	}
75
76	path = args->argv[0];
77	if (strcmp(path, "-") == 0) {
78		if (c == NULL) {
79			ctx->error(ctx, "%s: can't write to stdout", path);
80			return (-1);
81		}
82		evbuffer_add(c->stdout_data, pb->data, pb->size);
83		server_push_stdout(c);
84	} else {
85		if (c != NULL)
86			wd = c->cwd;
87		else if ((s = cmd_current_session(ctx, 0)) != NULL) {
88			wd = options_get_string(&s->options, "default-path");
89			if (*wd == '\0')
90				wd = s->cwd;
91		} else
92			wd = NULL;
93		if (wd != NULL && *wd != '\0') {
94			newpath = get_full_path(wd, path);
95			if (newpath != NULL)
96				path = newpath;
97		}
98
99		mask = umask(S_IRWXG | S_IRWXO);
100		if (args_has(self->args, 'a'))
101			f = fopen(path, "ab");
102		else
103			f = fopen(path, "wb");
104		umask(mask);
105		if (f == NULL) {
106			ctx->error(ctx, "%s: %s", path, strerror(errno));
107			return (-1);
108		}
109		if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
110			ctx->error(ctx, "%s: fwrite error", path);
111			fclose(f);
112			return (-1);
113		}
114		fclose(f);
115	}
116
117	return (0);
118}
119