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