From 146a3530859ebade88d032814bdf049dcff61bfb Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 1 Jan 2013 01:11:46 +0800 Subject: [PATCH 01/21] rename enum io_mode -> io_mode_t; make io_data_t::io_mode that type --- io.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/io.h b/io.h index faea6a0ce..f9e2c7f5f 100644 --- a/io.h +++ b/io.h @@ -8,7 +8,7 @@ using std::tr1::shared_ptr; /** Describes what type of IO operation an io_data_t represents */ -enum io_mode +enum io_mode_t { IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE }; @@ -26,7 +26,7 @@ private: public: /** Type of redirect */ - int io_mode; + io_mode_t io_mode; /** FD to redirect */ int fd; @@ -99,7 +99,7 @@ public: io_data_t() : out_buffer(), - io_mode(0), + io_mode(IO_FILE), fd(0), param1(), param2(), From 664fee5c6ee4214f72c24bed4256cc7a4b207483 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 1 Jan 2013 01:12:47 +0800 Subject: [PATCH 02/21] Use new IO_INVALID as default value of io_data_t::io_mode --- io.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/io.h b/io.h index f9e2c7f5f..d811f6ea2 100644 --- a/io.h +++ b/io.h @@ -10,7 +10,7 @@ using std::tr1::shared_ptr; */ enum io_mode_t { - IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE + IO_INVALID, IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE }; /** Represents an FD redirection */ @@ -99,7 +99,7 @@ public: io_data_t() : out_buffer(), - io_mode(IO_FILE), + io_mode(IO_INVALID), fd(0), param1(), param2(), From 424bb589a22cfa6b2ceaba2a9edc61c08e46f74a Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 1 Jan 2013 01:14:35 +0800 Subject: [PATCH 03/21] Make io_data_t destructor virtual --- io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io.h b/io.h index d811f6ea2..b7abbec76 100644 --- a/io.h +++ b/io.h @@ -108,7 +108,7 @@ public: { } - ~io_data_t() + virtual ~io_data_t() { free((void *)filename_cstr); } From 78ab7e7ba12036140941e145ed338a126125f487 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 1 Jan 2013 01:27:27 +0800 Subject: [PATCH 04/21] Introduce a macro CAST_INIT to abbreviate common static_cast's a bit This macro doesn't work with type names containing commas, but that doesn't seem to be too common in fish. --- common.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common.h b/common.h index 9c852f18f..268334002 100644 --- a/common.h +++ b/common.h @@ -22,6 +22,12 @@ #include #include "util.h" +/** + Avoid writing the type name twice in a common "static_cast-initialization". + Caveat: This doesn't work with type names containing commas! +*/ +#define CAST_INIT(type, dst, src) type dst = static_cast(src) + class completion_t; /* Common string type */ From 89993e9cbf95b55c941183f4db6ef41e4ce30029 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 1 Jan 2013 01:13:42 +0800 Subject: [PATCH 05/21] Let io_data_t constructor take optional io_mode and fd --- io.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/io.h b/io.h index b7abbec76..96f5cbaf4 100644 --- a/io.h +++ b/io.h @@ -97,10 +97,10 @@ public: /** Set to true if this is an input io redirection */ bool is_input; - io_data_t() : + io_data_t(io_mode_t m = IO_INVALID, int f=0) : out_buffer(), - io_mode(IO_INVALID), - fd(0), + io_mode(m), + fd(f), param1(), param2(), filename_cstr(NULL), From 165068c81d723c78cc3f82662082b263608bceb2 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Wed, 9 Jan 2013 15:49:12 +0800 Subject: [PATCH 06/21] Put io_data_t detail printing in virtual io_data_t::print --- io.cpp | 41 +++++++++++++++++++++++------------------ io.h | 2 ++ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/io.cpp b/io.cpp index 6a304014c..42c55f9fe 100644 --- a/io.cpp +++ b/io.cpp @@ -51,6 +51,28 @@ Utilities for io redirection. #include "io.h" +void io_data_t::print() const +{ + switch (io_mode) + { + case IO_FILE: + fprintf(stderr, "file (%s)\n", filename_cstr); + break; + case IO_PIPE: + fprintf(stderr, "pipe {%d, %d}\n", param1.pipe_fd[0], param1.pipe_fd[1]); + break; + case IO_FD: + fprintf(stderr, "FD map %d -> %d\n", param1.old_fd, fd); + break; + case IO_BUFFER: + fprintf(stderr, "buffer %p (size %lu)\n", out_buffer_ptr(), out_buffer_size()); + break; + case IO_CLOSE: + fprintf(stderr, "close %d\n", fd); + break; + } +} + void io_buffer_read(io_data_t *d) { exec_close(d->param1.pipe_fd[1]); @@ -195,24 +217,7 @@ void io_print(const io_chain_t &chain) { const shared_ptr &io = chain.at(i); fprintf(stderr, "\t%lu: fd:%d, input:%s, ", (unsigned long)i, io->fd, io->is_input ? "yes" : "no"); - switch (io->io_mode) - { - case IO_FILE: - fprintf(stderr, "file (%s)\n", io->filename_cstr); - break; - case IO_PIPE: - fprintf(stderr, "pipe {%d, %d}\n", io->param1.pipe_fd[0], io->param1.pipe_fd[1]); - break; - case IO_FD: - fprintf(stderr, "FD map %d -> %d\n", io->param1.old_fd, io->fd); - break; - case IO_BUFFER: - fprintf(stderr, "buffer %p (size %lu)\n", io->out_buffer_ptr(), io->out_buffer_size()); - break; - case IO_CLOSE: - fprintf(stderr, "close %d\n", io->fd); - break; - } + io->print(); } } diff --git a/io.h b/io.h index 96f5cbaf4..da47abe07 100644 --- a/io.h +++ b/io.h @@ -94,6 +94,8 @@ public: return out_buffer->size(); } + virtual void print() const; + /** Set to true if this is an input io redirection */ bool is_input; From 4e672427bc7fb0709a57335c9315f9afdc6e49ed Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Wed, 9 Jan 2013 15:56:52 +0800 Subject: [PATCH 07/21] parser.cpp: Put off initialization of new_io until mode is known --- parser.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/parser.cpp b/parser.cpp index a04abe409..14ad25c92 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1518,13 +1518,12 @@ void parser_t::parse_job_argument_list(process_t *p, break; } - new_io.reset(new io_data_t); errno = 0; - new_io->fd = fish_wcstoi(tok_last(tok), - &end, - 10); - if (new_io->fd < 0 || errno || *end) + int fd = fish_wcstoi(tok_last(tok), + &end, + 10); + if (fd < 0 || errno || *end) { error(SYNTAX_ERROR, tok_get_pos(tok), @@ -1575,25 +1574,25 @@ void parser_t::parse_job_argument_list(process_t *p, switch (type) { case TOK_REDIRECT_APPEND: - new_io->io_mode = IO_FILE; + new_io.reset(new io_data_t(IO_FILE, fd)); new_io->param2.flags = O_CREAT | O_APPEND | O_WRONLY; new_io->set_filename(target); break; case TOK_REDIRECT_OUT: - new_io->io_mode = IO_FILE; + new_io.reset(new io_data_t(IO_FILE, fd)); new_io->param2.flags = O_CREAT | O_WRONLY | O_TRUNC; new_io->set_filename(target); break; case TOK_REDIRECT_NOCLOB: - new_io->io_mode = IO_FILE; + new_io.reset(new io_data_t(IO_FILE, fd)); new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY; new_io->set_filename(target); break; case TOK_REDIRECT_IN: - new_io->io_mode = IO_FILE; + new_io.reset(new io_data_t(IO_FILE, fd)); new_io->param2.flags = O_RDONLY; new_io->set_filename(target); break; @@ -1602,13 +1601,13 @@ void parser_t::parse_job_argument_list(process_t *p, { if (target == L"-") { - new_io->io_mode = IO_CLOSE; + new_io.reset(new io_data_t(IO_CLOSE, fd)); } else { wchar_t *end; - new_io->io_mode = IO_FD; + new_io.reset(new io_data_t(IO_FD, fd)); errno = 0; new_io->param1.old_fd = fish_wcstoi(target.c_str(), &end, 10); From f1b375b042ad1564d00645579a54bb28ba3e30d1 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Wed, 9 Jan 2013 16:02:04 +0800 Subject: [PATCH 08/21] Split out io_close_t --- io.cpp | 8 +++++--- io.h | 11 +++++++++++ parser.cpp | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/io.cpp b/io.cpp index 42c55f9fe..33045bcf4 100644 --- a/io.cpp +++ b/io.cpp @@ -67,12 +67,14 @@ void io_data_t::print() const case IO_BUFFER: fprintf(stderr, "buffer %p (size %lu)\n", out_buffer_ptr(), out_buffer_size()); break; - case IO_CLOSE: - fprintf(stderr, "close %d\n", fd); - break; } } +void io_close_t::print() const +{ + fprintf(stderr, "close %d\n", fd); +} + void io_buffer_read(io_data_t *d) { exec_close(d->param1.pipe_fd[1]); diff --git a/io.h b/io.h index da47abe07..d7ddbd0ec 100644 --- a/io.h +++ b/io.h @@ -116,6 +116,17 @@ public: } }; +class io_close_t : public io_data_t +{ +public: + io_close_t(int f) : + io_data_t(IO_CLOSE, f) + { + } + + virtual void print() const; +}; + class io_chain_t : public std::vector > { public: diff --git a/parser.cpp b/parser.cpp index 14ad25c92..1c5f330b2 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1601,7 +1601,7 @@ void parser_t::parse_job_argument_list(process_t *p, { if (target == L"-") { - new_io.reset(new io_data_t(IO_CLOSE, fd)); + new_io.reset(new io_close_t(fd)); } else { From 6f35792c74612f4b754125a5cfe9c96baa7854b9 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 15 Jan 2013 15:37:33 +0800 Subject: [PATCH 09/21] Split out io_fd_t --- exec.cpp | 10 +++------- io.cpp | 8 +++++--- io.h | 22 ++++++++++++++++++---- parser.cpp | 10 ++++++---- postfork.cpp | 13 ++++++++----- 5 files changed, 40 insertions(+), 23 deletions(-) diff --git a/exec.cpp b/exec.cpp index e72a787f5..2aa13dc1b 100644 --- a/exec.cpp +++ b/exec.cpp @@ -406,11 +406,6 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t &out_chain, s */ case IO_FILE: { - out.reset(new io_data_t()); - out->fd = in->fd; - out->io_mode = IO_FD; - out->param2.close_old = 1; - int fd; if ((fd=open(in->filename_cstr, in->param2.flags, OPEN_MASK))==-1) { @@ -424,7 +419,7 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t &out_chain, s } opened_fds.push_back(fd); - out->param1.old_fd = fd; + out.reset(new io_fd_t(in->fd, fd, true)); break; } @@ -852,7 +847,8 @@ void exec(parser_t &parser, job_t *j) case IO_FD: { - builtin_stdin = in->param1.old_fd; + CAST_INIT(const io_fd_t *, in_fd, in.get()); + builtin_stdin = in_fd->old_fd; break; } case IO_PIPE: diff --git a/io.cpp b/io.cpp index 33045bcf4..8bbc07438 100644 --- a/io.cpp +++ b/io.cpp @@ -61,9 +61,6 @@ void io_data_t::print() const case IO_PIPE: fprintf(stderr, "pipe {%d, %d}\n", param1.pipe_fd[0], param1.pipe_fd[1]); break; - case IO_FD: - fprintf(stderr, "FD map %d -> %d\n", param1.old_fd, fd); - break; case IO_BUFFER: fprintf(stderr, "buffer %p (size %lu)\n", out_buffer_ptr(), out_buffer_size()); break; @@ -75,6 +72,11 @@ void io_close_t::print() const fprintf(stderr, "close %d\n", fd); } +void io_fd_t::print() const +{ + fprintf(stderr, "FD map %d -> %d\n", old_fd, fd); +} + void io_buffer_read(io_data_t *d) { exec_close(d->param1.pipe_fd[1]); diff --git a/io.h b/io.h index d7ddbd0ec..627bfc39c 100644 --- a/io.h +++ b/io.h @@ -37,8 +37,6 @@ public: { /** Fds for IO_PIPE and for IO_BUFFER */ int pipe_fd[2]; - /** fd to redirect specified fd to, for IO_FD */ - int old_fd; } param1; @@ -47,8 +45,6 @@ public: { /** file creation flags to send to open for IO_FILE */ int flags; - /** Whether to close old_fd for IO_FD */ - int close_old; } param2; /** Filename IO_FILE. malloc'd. This needs to be used after fork, so don't use wcstring here. */ @@ -127,6 +123,24 @@ public: virtual void print() const; }; +class io_fd_t : public io_data_t +{ +public: + /** fd to redirect specified fd to */ + int old_fd; + /** Whether to close old_fd */ + int close_old; + + virtual void print() const; + + io_fd_t(int f, int old, bool close = false) : + io_data_t(IO_FD, f), + old_fd(old), + close_old(close) + { + } +}; + class io_chain_t : public std::vector > { public: diff --git a/parser.cpp b/parser.cpp index 1c5f330b2..1329cea62 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1607,13 +1607,11 @@ void parser_t::parse_job_argument_list(process_t *p, { wchar_t *end; - new_io.reset(new io_data_t(IO_FD, fd)); errno = 0; - new_io->param1.old_fd = fish_wcstoi(target.c_str(), &end, 10); + int old_fd = fish_wcstoi(target.c_str(), &end, 10); - if ((new_io->param1.old_fd < 0) || - errno || *end) + if (old_fd < 0 || errno || *end) { error(SYNTAX_ERROR, tok_get_pos(tok), @@ -1622,6 +1620,10 @@ void parser_t::parse_job_argument_list(process_t *p, tok_next(tok); } + else + { + new_io.reset(new io_fd_t(fd, old_fd)); + } } break; } diff --git a/postfork.cpp b/postfork.cpp index 9b8913cec..a5602ad19 100644 --- a/postfork.cpp +++ b/postfork.cpp @@ -169,7 +169,7 @@ static int handle_child_io(io_chain_t &io_chain) io_data_t *io = io_chain.at(idx).get(); int tmp; - if (io->io_mode == IO_FD && io->fd == io->param1.old_fd) + if (io->io_mode == IO_FD && io->fd == static_cast(io)->old_fd) { continue; } @@ -232,7 +232,7 @@ static int handle_child_io(io_chain_t &io_chain) */ close(io->fd); - if (dup2(io->param1.old_fd, io->fd) == -1) + if (dup2(static_cast(io)->old_fd, io->fd) == -1) { debug_safe_int(1, FD_ERROR, io->fd); safe_perror("dup2"); @@ -443,9 +443,11 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil { shared_ptr io = j->io.at(idx); - if (io->io_mode == IO_FD && io->fd == io->param1.old_fd) + if (io->io_mode == IO_FD) { - continue; + CAST_INIT(const io_fd_t *, io_fd, io.get()); + if (io->fd == io_fd->old_fd) + continue; } if (io->fd > 2) @@ -472,8 +474,9 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil case IO_FD: { + CAST_INIT(const io_fd_t *, io_fd, io.get()); if (! err) - err = posix_spawn_file_actions_adddup2(actions, io->param1.old_fd /* from */, io->fd /* to */); + err = posix_spawn_file_actions_adddup2(actions, io_fd->old_fd /* from */, io->fd /* to */); break; } From 4b6bd7cae5e731f8e2bafeabca59e5aaabd6749d Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 15 Jan 2013 16:18:03 +0800 Subject: [PATCH 10/21] Split out io_file_t --- exec.cpp | 17 ++++++----- io.cpp | 8 ++++-- io.h | 51 +++++++++++++++++++-------------- parser.cpp | 81 ++++++++++++++++++++++++---------------------------- postfork.cpp | 14 +++++---- 5 files changed, 90 insertions(+), 81 deletions(-) diff --git a/exec.cpp b/exec.cpp index 2aa13dc1b..725b40bec 100644 --- a/exec.cpp +++ b/exec.cpp @@ -407,11 +407,12 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t &out_chain, s case IO_FILE: { int fd; - if ((fd=open(in->filename_cstr, in->param2.flags, OPEN_MASK))==-1) + CAST_INIT(io_file_t *, in_file, in.get()); + if ((fd=open(in_file->filename_cstr, in_file->flags, OPEN_MASK))==-1) { debug(1, FILE_ERROR, - in->filename_cstr); + in_file->filename_cstr); wperror(L"open"); success = false; @@ -516,7 +517,8 @@ static bool can_use_posix_spawn_for_job(const job_t *job, const process_t *proce const shared_ptr &io = job->io.at(idx); if (io->io_mode == IO_FILE) { - const char *path = io->filename_cstr; + CAST_INIT(const io_file_t *, io_file, io.get()); + const char *path = io_file->filename_cstr; /* This IO action is a file redirection. Only allow /dev/null, which is a common case we assume won't fail. */ if (strcmp(path, "/dev/null") != 0) { @@ -860,13 +862,14 @@ void exec(parser_t &parser, job_t *j) case IO_FILE: { /* Do not set CLO_EXEC because child needs access */ - builtin_stdin=open(in->filename_cstr, - in->param2.flags, OPEN_MASK); + CAST_INIT(const io_file_t *, in_file, in.get()); + builtin_stdin=open(in_file->filename_cstr, + in_file->flags, OPEN_MASK); if (builtin_stdin == -1) { debug(1, FILE_ERROR, - in->filename_cstr); + in_file->filename_cstr); wperror(L"open"); } else @@ -1158,7 +1161,7 @@ void exec(parser_t &parser, job_t *j) for (io_chain_t::iterator iter = j->io.begin(); iter != j->io.end(); iter++) { const shared_ptr &tmp_io = *iter; - if (tmp_io->io_mode == IO_FILE && strcmp(tmp_io->filename_cstr, "/dev/null") != 0) + if (tmp_io->io_mode == IO_FILE && strcmp(static_cast(tmp_io.get())->filename_cstr, "/dev/null") != 0) { skip_fork = false; break; diff --git a/io.cpp b/io.cpp index 8bbc07438..9eb29f2be 100644 --- a/io.cpp +++ b/io.cpp @@ -55,9 +55,6 @@ void io_data_t::print() const { switch (io_mode) { - case IO_FILE: - fprintf(stderr, "file (%s)\n", filename_cstr); - break; case IO_PIPE: fprintf(stderr, "pipe {%d, %d}\n", param1.pipe_fd[0], param1.pipe_fd[1]); break; @@ -77,6 +74,11 @@ void io_fd_t::print() const fprintf(stderr, "FD map %d -> %d\n", old_fd, fd); } +void io_file_t::print() const +{ + fprintf(stderr, "file (%s)\n", filename_cstr); +} + void io_buffer_read(io_data_t *d) { exec_close(d->param1.pipe_fd[1]); diff --git a/io.h b/io.h index 627bfc39c..e13f961c5 100644 --- a/io.h +++ b/io.h @@ -39,24 +39,6 @@ public: int pipe_fd[2]; } param1; - - /** Second type-specific paramter for redirection */ - union - { - /** file creation flags to send to open for IO_FILE */ - int flags; - } param2; - - /** Filename IO_FILE. malloc'd. This needs to be used after fork, so don't use wcstring here. */ - const char *filename_cstr; - - /** Convenience to set filename_cstr via wcstring */ - void set_filename(const wcstring &str) - { - free((void *)filename_cstr); - filename_cstr = wcs2str(str.c_str()); - } - /** Function to create the output buffer */ void out_buffer_create() { @@ -100,15 +82,12 @@ public: io_mode(m), fd(f), param1(), - param2(), - filename_cstr(NULL), is_input(0) { } virtual ~io_data_t() { - free((void *)filename_cstr); } }; @@ -141,6 +120,36 @@ public: } }; +class io_file_t : public io_data_t +{ +public: + /** Filename, malloc'd. This needs to be used after fork, so don't use wcstring here. */ + const char *filename_cstr; + /** file creation flags to send to open */ + int flags; + + /** Convenience to set filename_cstr via wcstring */ + void set_filename(const wcstring &str) + { + free((void *)filename_cstr); + filename_cstr = wcs2str(str.c_str()); + } + + virtual void print() const; + + io_file_t(int f, const char *fname = NULL, int fl = 0) : + io_data_t(IO_FILE, f), + filename_cstr(fname ? strdup(fname) : NULL), + flags(fl) + { + } + + virtual ~io_file_t() + { + free((void *)filename_cstr); + } +}; + class io_chain_t : public std::vector > { public: diff --git a/parser.cpp b/parser.cpp index 1329cea62..f2ed3f2d7 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1568,67 +1568,60 @@ void parser_t::parse_job_argument_list(process_t *p, _(L"Invalid IO redirection")); tok_next(tok); } + else if (type == TOK_REDIRECT_FD) + { + if (target == L"-") + { + new_io.reset(new io_close_t(fd)); + } + else + { + wchar_t *end; + + errno = 0; + + int old_fd = fish_wcstoi(target.c_str(), &end, 10); + + if (old_fd < 0 || errno || *end) + { + error(SYNTAX_ERROR, + tok_get_pos(tok), + _(L"Requested redirection to something that is not a file descriptor %ls"), + target.c_str()); + + tok_next(tok); + } + else + { + new_io.reset(new io_fd_t(fd, old_fd)); + } + } + } else { - + int flags = 0; switch (type) { case TOK_REDIRECT_APPEND: - new_io.reset(new io_data_t(IO_FILE, fd)); - new_io->param2.flags = O_CREAT | O_APPEND | O_WRONLY; - new_io->set_filename(target); + flags = O_CREAT | O_APPEND | O_WRONLY; break; case TOK_REDIRECT_OUT: - new_io.reset(new io_data_t(IO_FILE, fd)); - new_io->param2.flags = O_CREAT | O_WRONLY | O_TRUNC; - new_io->set_filename(target); + flags = O_CREAT | O_WRONLY | O_TRUNC; break; case TOK_REDIRECT_NOCLOB: - new_io.reset(new io_data_t(IO_FILE, fd)); - new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY; - new_io->set_filename(target); + flags = O_CREAT | O_EXCL | O_WRONLY; break; case TOK_REDIRECT_IN: - new_io.reset(new io_data_t(IO_FILE, fd)); - new_io->param2.flags = O_RDONLY; - new_io->set_filename(target); + flags = O_RDONLY; break; - case TOK_REDIRECT_FD: - { - if (target == L"-") - { - new_io.reset(new io_close_t(fd)); - } - else - { - wchar_t *end; - - errno = 0; - - int old_fd = fish_wcstoi(target.c_str(), &end, 10); - - if (old_fd < 0 || errno || *end) - { - error(SYNTAX_ERROR, - tok_get_pos(tok), - _(L"Requested redirection to something that is not a file descriptor %ls"), - target.c_str()); - - tok_next(tok); - } - else - { - new_io.reset(new io_fd_t(fd, old_fd)); - } - } - break; - } } - + io_file_t *new_io_file = new io_file_t(fd, NULL, flags); + new_io_file->set_filename(target); + new_io.reset(new_io_file); } } diff --git a/postfork.cpp b/postfork.cpp index a5602ad19..17a46350a 100644 --- a/postfork.cpp +++ b/postfork.cpp @@ -189,17 +189,18 @@ static int handle_child_io(io_chain_t &io_chain) case IO_FILE: { // Here we definitely do not want to set CLO_EXEC because our child needs access - if ((tmp=open(io->filename_cstr, - io->param2.flags, OPEN_MASK))==-1) + CAST_INIT(io_file_t *, io_file, io); + if ((tmp=open(io_file->filename_cstr, + io_file->flags, OPEN_MASK))==-1) { - if ((io->param2.flags & O_EXCL) && + if ((io_file->flags & O_EXCL) && (errno ==EEXIST)) { - debug_safe(1, NOCLOB_ERROR, io->filename_cstr); + debug_safe(1, NOCLOB_ERROR, io_file->filename_cstr); } else { - debug_safe(1, FILE_ERROR, io->filename_cstr); + debug_safe(1, FILE_ERROR, io_file->filename_cstr); safe_perror("open"); } @@ -467,8 +468,9 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil case IO_FILE: { + CAST_INIT(const io_file_t *, io_file, io.get()); if (! err) - err = posix_spawn_file_actions_addopen(actions, io->fd, io->filename_cstr, io->param2.flags /* mode */, OPEN_MASK); + err = posix_spawn_file_actions_addopen(actions, io->fd, io_file->filename_cstr, io_file->flags /* mode */, OPEN_MASK); break; } From a20e0b9e2eb25b16e8416ac7758c2da0216dc6d8 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 15 Jan 2013 16:44:31 +0800 Subject: [PATCH 11/21] Split out io_buffer_t, make input_redirect in exec() a raw pointer --- exec.cpp | 19 +++++------ io.cpp | 18 +++++------ io.h | 92 ++++++++++++++++++++++++++++++------------------------ proc.cpp | 4 +-- reader.cpp | 4 +-- 5 files changed, 75 insertions(+), 62 deletions(-) diff --git a/exec.cpp b/exec.cpp index 725b40bec..a59cd55ed 100644 --- a/exec.cpp +++ b/exec.cpp @@ -538,7 +538,7 @@ void exec(parser_t &parser, job_t *j) int mypipe[2]; sigset_t chldset; - shared_ptr io_buffer; + shared_ptr io_buffer; /* Set to true if something goes wrong while exec:ing the job, in @@ -566,24 +566,24 @@ void exec(parser_t &parser, job_t *j) io_duplicate_prepend(parser.block_io, j->io); } - shared_ptr input_redirect; + const io_buffer_t *input_redirect = 0; for (size_t idx = 0; idx < j->io.size(); idx++) { - input_redirect = j->io.at(idx); + shared_ptr &io = j->io.at(idx); - if ((input_redirect->io_mode == IO_BUFFER) && - input_redirect->is_input) + if ((io->io_mode == IO_BUFFER) && io->is_input) { /* Input redirection - create a new gobetween process to take - care of buffering + care of buffering, save the redirection in input_redirect */ process_t *fake = new process_t(); fake->type = INTERNAL_BUFFER; fake->pipe_write_fd = 1; - j->first_process->pipe_read_fd = input_redirect->fd; + j->first_process->pipe_read_fd = io->fd; fake->next = j->first_process; j->first_process = fake; + input_redirect = static_cast(io.get()); break; } } @@ -1135,8 +1135,9 @@ void exec(parser_t &parser, job_t *j) (! get_stdout_buffer().empty()) && (buffer_stdout)) { + CAST_INIT(io_buffer_t *, io_buffer, io.get()); const std::string res = wcs2string(get_stdout_buffer()); - io->out_buffer_append(res.c_str(), res.size()); + io_buffer->out_buffer_append(res.c_str(), res.size()); skip_fork = true; } @@ -1410,7 +1411,7 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst) is_subshell=1; - const shared_ptr io_buffer(io_buffer_create(0)); + const shared_ptr io_buffer(io_buffer_create(0)); prev_status = proc_get_last_status(); diff --git a/io.cpp b/io.cpp index 9eb29f2be..37ca25a1c 100644 --- a/io.cpp +++ b/io.cpp @@ -58,9 +58,6 @@ void io_data_t::print() const case IO_PIPE: fprintf(stderr, "pipe {%d, %d}\n", param1.pipe_fd[0], param1.pipe_fd[1]); break; - case IO_BUFFER: - fprintf(stderr, "buffer %p (size %lu)\n", out_buffer_ptr(), out_buffer_size()); - break; } } @@ -79,7 +76,12 @@ void io_file_t::print() const fprintf(stderr, "file (%s)\n", filename_cstr); } -void io_buffer_read(io_data_t *d) +void io_buffer_t::print() const +{ + fprintf(stderr, "buffer %p (size %lu)\n", out_buffer_ptr(), out_buffer_size()); +} + +void io_buffer_read(io_buffer_t *d) { exec_close(d->param1.pipe_fd[1]); @@ -128,14 +130,12 @@ void io_buffer_read(io_data_t *d) } -io_data_t *io_buffer_create(bool is_input) +io_buffer_t *io_buffer_create(bool is_input) { bool success = true; - io_data_t *buffer_redirect = new io_data_t; + io_buffer_t *buffer_redirect = new io_buffer_t(is_input ? 0 : 1); buffer_redirect->out_buffer_create(); - buffer_redirect->io_mode = IO_BUFFER; buffer_redirect->is_input = is_input ? true : false; - buffer_redirect->fd=is_input?0:1; if (exec_pipe(buffer_redirect->param1.pipe_fd) == -1) { @@ -161,7 +161,7 @@ io_data_t *io_buffer_create(bool is_input) return buffer_redirect; } -void io_buffer_destroy(const shared_ptr &io_buffer) +void io_buffer_destroy(const shared_ptr &io_buffer) { /** diff --git a/io.h b/io.h index e13f961c5..4f0edd8ac 100644 --- a/io.h +++ b/io.h @@ -17,9 +17,6 @@ enum io_mode_t class io_data_t { private: - /** buffer to save output in for IO_BUFFER. Note that in the original fish, the buffer was a pointer to a buffer_t stored in the param2 union down below, and when an io_data_t was duplicated the pointer was copied so that two io_data_ts referenced the same buffer. It's not clear to me how this was ever cleaned up correctly. But it's important that they share the same buffer for reasons I don't yet understand either. We can get correct sharing and cleanup with shared_ptr. */ - shared_ptr > out_buffer; - /* No assignment or copying allowed */ io_data_t(const io_data_t &rhs); void operator=(const io_data_t &rhs); @@ -39,46 +36,12 @@ public: int pipe_fd[2]; } param1; - /** Function to create the output buffer */ - void out_buffer_create() - { - out_buffer.reset(new std::vector); - } - - /** Function to append to the buffer */ - void out_buffer_append(const char *ptr, size_t count) - { - assert(out_buffer.get() != NULL); - out_buffer->insert(out_buffer->end(), ptr, ptr + count); - } - - /** Function to get a pointer to the buffer */ - char *out_buffer_ptr(void) - { - assert(out_buffer.get() != NULL); - return out_buffer->empty() ? NULL : &out_buffer->at(0); - } - - const char *out_buffer_ptr(void) const - { - assert(out_buffer.get() != NULL); - return out_buffer->empty() ? NULL : &out_buffer->at(0); - } - - /** Function to get the size of the buffer */ - size_t out_buffer_size(void) const - { - assert(out_buffer.get() != NULL); - return out_buffer->size(); - } - virtual void print() const; /** Set to true if this is an input io redirection */ bool is_input; io_data_t(io_mode_t m = IO_INVALID, int f=0) : - out_buffer(), io_mode(m), fd(f), param1(), @@ -150,6 +113,55 @@ public: } }; +class io_buffer_t : public io_data_t +{ +private: + /** buffer to save output in */ + shared_ptr > out_buffer; + +public: + virtual void print() const; + + io_buffer_t(int f): + io_data_t(IO_BUFFER, f), + out_buffer() + { + } + + /** Function to create the output buffer */ + void out_buffer_create() + { + out_buffer.reset(new std::vector); + } + + /** Function to append to the buffer */ + void out_buffer_append(const char *ptr, size_t count) + { + assert(out_buffer.get() != NULL); + out_buffer->insert(out_buffer->end(), ptr, ptr + count); + } + + /** Function to get a pointer to the buffer */ + char *out_buffer_ptr(void) + { + assert(out_buffer.get() != NULL); + return out_buffer->empty() ? NULL : &out_buffer->at(0); + } + + const char *out_buffer_ptr(void) const + { + assert(out_buffer.get() != NULL); + return out_buffer->empty() ? NULL : &out_buffer->at(0); + } + + /** Function to get the size of the buffer */ + size_t out_buffer_size(void) const + { + assert(out_buffer.get() != NULL); + return out_buffer->size(); + } +}; + class io_chain_t : public std::vector > { public: @@ -190,7 +202,7 @@ shared_ptr io_chain_get(io_chain_t &src, int fd); /** Free all resources used by a IO_BUFFER type io redirection. */ -void io_buffer_destroy(const shared_ptr &io_buffer); +void io_buffer_destroy(const shared_ptr &io_buffer); /** Create a IO_BUFFER type io redirection, complete with a pipe and a @@ -201,12 +213,12 @@ void io_buffer_destroy(const shared_ptr &io_buffer); used to buffer the output of a command, or non-zero to buffer the input to a command. */ -io_data_t *io_buffer_create(bool is_input); +io_buffer_t *io_buffer_create(bool is_input); /** Close output pipe, and read from input pipe until eof. */ -void io_buffer_read(io_data_t *d); +void io_buffer_read(io_buffer_t *d); /** Print debug information about the specified IO redirection chain to stderr. */ void io_print(const io_chain_t &chain); diff --git a/proc.cpp b/proc.cpp index 1b37f1496..2e6e32ee9 100644 --- a/proc.cpp +++ b/proc.cpp @@ -902,7 +902,7 @@ static int select_try(job_t *j) */ static void read_try(job_t *j) { - io_data_t *buff=NULL; + io_buffer_t *buff=NULL; /* Find the last buffer, which is the one we want to read from @@ -912,7 +912,7 @@ static void read_try(job_t *j) io_data_t *d = j->io.at(idx).get(); if (d->io_mode == IO_BUFFER) { - buff=d; + buff = static_cast(d); } } diff --git a/reader.cpp b/reader.cpp index 05dd01a64..693b220f5 100644 --- a/reader.cpp +++ b/reader.cpp @@ -1064,7 +1064,7 @@ static void run_pager(const wcstring &prefix, int is_quoted, const std::vector in(io_buffer_create(true)); + shared_ptr in(io_buffer_create(true)); in->fd = 3; escaped_separator = escape(COMPLETE_SEP_STR, 1); @@ -1133,7 +1133,7 @@ static void run_pager(const wcstring &prefix, int is_quoted, const std::vector out(io_buffer_create(false)); + shared_ptr out(io_buffer_create(false)); out->fd = 4; parser_t &parser = parser_t::principal_parser(); From 0f443ef37b21bdc7d97db394842055f7b6e755a6 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 15 Jan 2013 17:02:46 +0800 Subject: [PATCH 12/21] Convert io_buffer_destroy to ~io_buffer_t --- exec.cpp | 3 --- io.cpp | 8 ++++---- io.h | 7 ++----- reader.cpp | 3 --- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/exec.cpp b/exec.cpp index a59cd55ed..428978115 100644 --- a/exec.cpp +++ b/exec.cpp @@ -1054,8 +1054,6 @@ void exec(parser_t &parser, job_t *j) p->completed = 1; } - io_buffer_destroy(io_buffer); - io_buffer.reset(); break; @@ -1455,7 +1453,6 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst) } } - io_buffer_destroy(io_buffer); return status; } diff --git a/io.cpp b/io.cpp index 37ca25a1c..6970a1c9d 100644 --- a/io.cpp +++ b/io.cpp @@ -161,19 +161,19 @@ io_buffer_t *io_buffer_create(bool is_input) return buffer_redirect; } -void io_buffer_destroy(const shared_ptr &io_buffer) +io_buffer_t::~io_buffer_t() { /** If this is an input buffer, then io_read_buffer will not have been called, and we need to close the output fd as well. */ - if (io_buffer->is_input) + if (is_input) { - exec_close(io_buffer->param1.pipe_fd[1]); + exec_close(param1.pipe_fd[1]); } - exec_close(io_buffer->param1.pipe_fd[0]); + exec_close(param1.pipe_fd[0]); /* Dont free fd for writing. This should already be free'd before diff --git a/io.h b/io.h index 4f0edd8ac..cc2a37667 100644 --- a/io.h +++ b/io.h @@ -128,6 +128,8 @@ public: { } + ~io_buffer_t(); + /** Function to create the output buffer */ void out_buffer_create() { @@ -199,11 +201,6 @@ shared_ptr io_chain_get(const io_chain_t &src, int fd); shared_ptr io_chain_get(io_chain_t &src, int fd); -/** - Free all resources used by a IO_BUFFER type io redirection. -*/ -void io_buffer_destroy(const shared_ptr &io_buffer); - /** Create a IO_BUFFER type io redirection, complete with a pipe and a vector for output. The default file descriptor used is 1 for diff --git a/reader.cpp b/reader.cpp index 693b220f5..56e9f8100 100644 --- a/reader.cpp +++ b/reader.cpp @@ -1158,9 +1158,6 @@ static void run_pager(const wcstring &prefix, int is_quoted, const std::vector Date: Tue, 15 Jan 2013 17:07:30 +0800 Subject: [PATCH 13/21] Convert io_buffer_create to static io_buffer_t::create, make io_buffer_t constructor private --- exec.cpp | 6 +++--- io.cpp | 2 +- io.h | 28 ++++++++++++++-------------- reader.cpp | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/exec.cpp b/exec.cpp index 428978115..c11d36dfe 100644 --- a/exec.cpp +++ b/exec.cpp @@ -801,7 +801,7 @@ void exec(parser_t &parser, job_t *j) if (p->next) { - io_buffer.reset(io_buffer_create(0)); + io_buffer.reset(io_buffer_t::create(0)); j->io.push_back(io_buffer); } @@ -818,7 +818,7 @@ void exec(parser_t &parser, job_t *j) { if (p->next) { - io_buffer.reset(io_buffer_create(0)); + io_buffer.reset(io_buffer_t::create(0)); j->io.push_back(io_buffer); } @@ -1409,7 +1409,7 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst) is_subshell=1; - const shared_ptr io_buffer(io_buffer_create(0)); + const shared_ptr io_buffer(io_buffer_t::create(0)); prev_status = proc_get_last_status(); diff --git a/io.cpp b/io.cpp index 6970a1c9d..4dfd811e2 100644 --- a/io.cpp +++ b/io.cpp @@ -130,7 +130,7 @@ void io_buffer_read(io_buffer_t *d) } -io_buffer_t *io_buffer_create(bool is_input) +io_buffer_t *io_buffer_t::create(bool is_input) { bool success = true; io_buffer_t *buffer_redirect = new io_buffer_t(is_input ? 0 : 1); diff --git a/io.h b/io.h index cc2a37667..0c39963fc 100644 --- a/io.h +++ b/io.h @@ -119,15 +119,15 @@ private: /** buffer to save output in */ shared_ptr > out_buffer; -public: - virtual void print() const; - io_buffer_t(int f): io_data_t(IO_BUFFER, f), out_buffer() { } +public: + virtual void print() const; + ~io_buffer_t(); /** Function to create the output buffer */ @@ -162,6 +162,17 @@ public: assert(out_buffer.get() != NULL); return out_buffer->size(); } + + /** + Create a IO_BUFFER type io redirection, complete with a pipe and a + vector for output. The default file descriptor used is 1 for + output buffering and 0 for input buffering. + + \param is_input set this parameter to zero if the buffer should be + used to buffer the output of a command, or non-zero to buffer the + input to a command. + */ + static io_buffer_t *create(bool is_input); }; class io_chain_t : public std::vector > @@ -201,17 +212,6 @@ shared_ptr io_chain_get(const io_chain_t &src, int fd); shared_ptr io_chain_get(io_chain_t &src, int fd); -/** - Create a IO_BUFFER type io redirection, complete with a pipe and a - vector for output. The default file descriptor used is 1 for - output buffering and 0 for input buffering. - - \param is_input set this parameter to zero if the buffer should be - used to buffer the output of a command, or non-zero to buffer the - input to a command. -*/ -io_buffer_t *io_buffer_create(bool is_input); - /** Close output pipe, and read from input pipe until eof. */ diff --git a/reader.cpp b/reader.cpp index 56e9f8100..477795837 100644 --- a/reader.cpp +++ b/reader.cpp @@ -1064,7 +1064,7 @@ static void run_pager(const wcstring &prefix, int is_quoted, const std::vector in(io_buffer_create(true)); + shared_ptr in(io_buffer_t::create(true)); in->fd = 3; escaped_separator = escape(COMPLETE_SEP_STR, 1); @@ -1133,7 +1133,7 @@ static void run_pager(const wcstring &prefix, int is_quoted, const std::vector out(io_buffer_create(false)); + shared_ptr out(io_buffer_t::create(false)); out->fd = 4; parser_t &parser = parser_t::principal_parser(); From df0c1eb32c93ea72318f351c4c5867b8bbf47caf Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Wed, 16 Jan 2013 11:30:18 +0800 Subject: [PATCH 14/21] Add missing virtual qualifier to ~io_buffer_t --- io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io.h b/io.h index 0c39963fc..30d0dfe22 100644 --- a/io.h +++ b/io.h @@ -128,7 +128,7 @@ private: public: virtual void print() const; - ~io_buffer_t(); + virtual ~io_buffer_t(); /** Function to create the output buffer */ void out_buffer_create() From e020ad0c068861325dca1655cb0ed487a22b67c5 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 15 Jan 2013 17:10:40 +0800 Subject: [PATCH 15/21] Convert io_buffer_read to io_buffer_t::read --- exec.cpp | 4 ++-- io.cpp | 18 +++++++++--------- io.h | 10 +++++----- reader.cpp | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/exec.cpp b/exec.cpp index c11d36dfe..4c6e8bfc1 100644 --- a/exec.cpp +++ b/exec.cpp @@ -1008,7 +1008,7 @@ void exec(parser_t &parser, job_t *j) io_remove(j->io, io_buffer); - io_buffer_read(io_buffer.get()); + io_buffer->read(); const char *buffer = io_buffer->out_buffer_ptr(); size_t count = io_buffer->out_buffer_size(); @@ -1423,7 +1423,7 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst) status = proc_get_last_status(); } - io_buffer_read(io_buffer.get()); + io_buffer->read(); proc_set_last_status(prev_status); diff --git a/io.cpp b/io.cpp index 4dfd811e2..0020659cf 100644 --- a/io.cpp +++ b/io.cpp @@ -81,23 +81,23 @@ void io_buffer_t::print() const fprintf(stderr, "buffer %p (size %lu)\n", out_buffer_ptr(), out_buffer_size()); } -void io_buffer_read(io_buffer_t *d) +void io_buffer_t::read() { - exec_close(d->param1.pipe_fd[1]); + exec_close(param1.pipe_fd[1]); - if (d->io_mode == IO_BUFFER) + if (io_mode == IO_BUFFER) { - /* if( fcntl( d->param1.pipe_fd[0], F_SETFL, 0 ) ) + /* if( fcntl( param1.pipe_fd[0], F_SETFL, 0 ) ) { wperror( L"fcntl" ); return; } */ - debug(4, L"io_buffer_read: blocking read on fd %d", d->param1.pipe_fd[0]); + debug(4, L"io_buffer_t::read: blocking read on fd %d", param1.pipe_fd[0]); while (1) { char b[4096]; long l; - l=read_blocked(d->param1.pipe_fd[0], b, 4096); + l=read_blocked(param1.pipe_fd[0], b, 4096); if (l==0) { break; @@ -115,15 +115,15 @@ void io_buffer_read(io_buffer_t *d) { debug(1, _(L"An error occured while reading output from code block on file descriptor %d"), - d->param1.pipe_fd[0]); - wperror(L"io_buffer_read"); + param1.pipe_fd[0]); + wperror(L"io_buffer_t::read"); } break; } else { - d->out_buffer_append(b, l); + out_buffer_append(b, l); } } } diff --git a/io.h b/io.h index 30d0dfe22..62087037c 100644 --- a/io.h +++ b/io.h @@ -163,6 +163,11 @@ public: return out_buffer->size(); } + /** + Close output pipe, and read from input pipe until eof. + */ + void read(); + /** Create a IO_BUFFER type io redirection, complete with a pipe and a vector for output. The default file descriptor used is 1 for @@ -212,11 +217,6 @@ shared_ptr io_chain_get(const io_chain_t &src, int fd); shared_ptr io_chain_get(io_chain_t &src, int fd); -/** - Close output pipe, and read from input pipe until eof. -*/ -void io_buffer_read(io_buffer_t *d); - /** Print debug information about the specified IO redirection chain to stderr. */ void io_print(const io_chain_t &chain); diff --git a/reader.cpp b/reader.cpp index 477795837..f90df311f 100644 --- a/reader.cpp +++ b/reader.cpp @@ -1143,7 +1143,7 @@ static void run_pager(const wcstring &prefix, int is_quoted, const std::vectorread(); int nil=0; out->out_buffer_append((char *)&nil, 1); From 00b6431ad9ec17f551b5ea175a46e5d63c181fc7 Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 15 Jan 2013 17:31:36 +0800 Subject: [PATCH 16/21] Split out io_pipe_t, let io_buffer_t inherit it --- exec.cpp | 29 +++++++++++++---------------- io.cpp | 29 ++++++++++++++--------------- io.h | 29 +++++++++++++++++------------ postfork.cpp | 33 ++++++++++++++++++--------------- proc.cpp | 9 +++++---- 5 files changed, 67 insertions(+), 62 deletions(-) diff --git a/exec.cpp b/exec.cpp index 4c6e8bfc1..9e63c3d11 100644 --- a/exec.cpp +++ b/exec.cpp @@ -164,8 +164,8 @@ static bool use_fd_in_pipe(int fd, const io_chain_t &io_chain) if ((io->io_mode == IO_BUFFER) || (io->io_mode == IO_PIPE)) { - if (io->param1.pipe_fd[0] == fd || - io->param1.pipe_fd[1] == fd) + CAST_INIT(const io_pipe_t *, io_pipe, io.get()); + if (io_pipe->pipe_fd[0] == fd || io_pipe->pipe_fd[1] == fd) return true; } } @@ -615,17 +615,13 @@ void exec(parser_t &parser, job_t *j) } - shared_ptr pipe_read(new io_data_t); - pipe_read->fd = 0; - pipe_read->io_mode = IO_PIPE; + shared_ptr pipe_read(new io_pipe_t(0)); pipe_read->is_input = 1; - pipe_read->param1.pipe_fd[0] = pipe_read->param1.pipe_fd[1] = -1; + pipe_read->pipe_fd[0] = pipe_read->pipe_fd[1] = -1; - shared_ptr pipe_write(new io_data_t); - pipe_write->fd = 1; - pipe_write->io_mode = IO_PIPE; + shared_ptr pipe_write(new io_pipe_t(1)); pipe_write->is_input = 0; - pipe_write->param1.pipe_fd[0] = pipe_write->param1.pipe_fd[1] = -1; + pipe_write->pipe_fd[0] = pipe_write->pipe_fd[1] = -1; j->io.push_back(pipe_write); @@ -738,7 +734,7 @@ void exec(parser_t &parser, job_t *j) break; } - memcpy(pipe_write->param1.pipe_fd, mypipe, sizeof(int)*2); + memcpy(pipe_write->pipe_fd, mypipe, sizeof(int)*2); } else { @@ -855,7 +851,8 @@ void exec(parser_t &parser, job_t *j) } case IO_PIPE: { - builtin_stdin = in->param1.pipe_fd[0]; + CAST_INIT(const io_pipe_t *, in_pipe, in.get()); + builtin_stdin = in_pipe->pipe_fd[0]; break; } @@ -908,7 +905,7 @@ void exec(parser_t &parser, job_t *j) } else { - builtin_stdin = pipe_read->param1.pipe_fd[0]; + builtin_stdin = pipe_read->pipe_fd[0]; } if (builtin_stdin == -1) @@ -1332,14 +1329,14 @@ void exec(parser_t &parser, job_t *j) Close the pipe the current process uses to read from the previous process_t */ - if (pipe_read->param1.pipe_fd[0] >= 0) - exec_close(pipe_read->param1.pipe_fd[0]); + if (pipe_read->pipe_fd[0] >= 0) + exec_close(pipe_read->pipe_fd[0]); /* Set up the pipe the next process uses to read from the current process_t */ if (p_wants_pipe) - pipe_read->param1.pipe_fd[0] = mypipe[0]; + pipe_read->pipe_fd[0] = mypipe[0]; /* If there is a next process in the pipeline, close the diff --git a/io.cpp b/io.cpp index 0020659cf..4ec1d2bf4 100644 --- a/io.cpp +++ b/io.cpp @@ -53,12 +53,6 @@ Utilities for io redirection. void io_data_t::print() const { - switch (io_mode) - { - case IO_PIPE: - fprintf(stderr, "pipe {%d, %d}\n", param1.pipe_fd[0], param1.pipe_fd[1]); - break; - } } void io_close_t::print() const @@ -76,6 +70,11 @@ void io_file_t::print() const fprintf(stderr, "file (%s)\n", filename_cstr); } +void io_pipe_t::print() const +{ + fprintf(stderr, "pipe {%d, %d}\n", pipe_fd[0], pipe_fd[1]); +} + void io_buffer_t::print() const { fprintf(stderr, "buffer %p (size %lu)\n", out_buffer_ptr(), out_buffer_size()); @@ -83,21 +82,21 @@ void io_buffer_t::print() const void io_buffer_t::read() { - exec_close(param1.pipe_fd[1]); + exec_close(pipe_fd[1]); if (io_mode == IO_BUFFER) { - /* if( fcntl( param1.pipe_fd[0], F_SETFL, 0 ) ) + /* if( fcntl( pipe_fd[0], F_SETFL, 0 ) ) { wperror( L"fcntl" ); return; } */ - debug(4, L"io_buffer_t::read: blocking read on fd %d", param1.pipe_fd[0]); + debug(4, L"io_buffer_t::read: blocking read on fd %d", pipe_fd[0]); while (1) { char b[4096]; long l; - l=read_blocked(param1.pipe_fd[0], b, 4096); + l=read_blocked(pipe_fd[0], b, 4096); if (l==0) { break; @@ -115,7 +114,7 @@ void io_buffer_t::read() { debug(1, _(L"An error occured while reading output from code block on file descriptor %d"), - param1.pipe_fd[0]); + pipe_fd[0]); wperror(L"io_buffer_t::read"); } @@ -137,13 +136,13 @@ io_buffer_t *io_buffer_t::create(bool is_input) buffer_redirect->out_buffer_create(); buffer_redirect->is_input = is_input ? true : false; - if (exec_pipe(buffer_redirect->param1.pipe_fd) == -1) + if (exec_pipe(buffer_redirect->pipe_fd) == -1) { debug(1, PIPE_ERROR); wperror(L"pipe"); success = false; } - else if (fcntl(buffer_redirect->param1.pipe_fd[0], + else if (fcntl(buffer_redirect->pipe_fd[0], F_SETFL, O_NONBLOCK)) { @@ -170,10 +169,10 @@ io_buffer_t::~io_buffer_t() */ if (is_input) { - exec_close(param1.pipe_fd[1]); + exec_close(pipe_fd[1]); } - exec_close(param1.pipe_fd[0]); + exec_close(pipe_fd[0]); /* Dont free fd for writing. This should already be free'd before diff --git a/io.h b/io.h index 62087037c..5f3c1a678 100644 --- a/io.h +++ b/io.h @@ -27,15 +27,6 @@ public: /** FD to redirect */ int fd; - /** - Type-specific parameter for redirection - */ - union - { - /** Fds for IO_PIPE and for IO_BUFFER */ - int pipe_fd[2]; - } param1; - virtual void print() const; /** Set to true if this is an input io redirection */ @@ -44,7 +35,6 @@ public: io_data_t(io_mode_t m = IO_INVALID, int f=0) : io_mode(m), fd(f), - param1(), is_input(0) { } @@ -113,16 +103,31 @@ public: } }; -class io_buffer_t : public io_data_t +class io_pipe_t : public io_data_t +{ +public: + int pipe_fd[2]; + + virtual void print() const; + + io_pipe_t(int f): + io_data_t(IO_PIPE, f), + pipe_fd() + { + } +}; + +class io_buffer_t : public io_pipe_t { private: /** buffer to save output in */ shared_ptr > out_buffer; io_buffer_t(int f): - io_data_t(IO_BUFFER, f), + io_pipe_t(f), out_buffer() { + io_mode = IO_BUFFER; } public: diff --git a/postfork.cpp b/postfork.cpp index 17a46350a..558805ab4 100644 --- a/postfork.cpp +++ b/postfork.cpp @@ -117,15 +117,16 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain) for (size_t j = 0; j < max; j++) { /* We're only interested in pipes */ - io_data_t *possible_conflict = io_chain.at(j).get(); - if (possible_conflict->io_mode != IO_PIPE && possible_conflict->io_mode != IO_BUFFER) + io_data_t *io = io_chain.at(j).get(); + if (io->io_mode != IO_PIPE && io->io_mode != IO_BUFFER) continue; + CAST_INIT(io_pipe_t *, possible_conflict, io); /* If the pipe is a conflict, dup it to some other value */ for (int k=0; k<2; k++) { /* If it's not a conflict, we don't care */ - if (possible_conflict->param1.pipe_fd[k] != fd_to_free) + if (possible_conflict->pipe_fd[k] != fd_to_free) continue; /* Repeat until we have a replacement fd */ @@ -140,7 +141,7 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain) FATAL_EXIT(); } } - possible_conflict->param1.pipe_fd[k] = replacement_fd; + possible_conflict->pipe_fd[k] = replacement_fd; } } } @@ -245,6 +246,7 @@ static int handle_child_io(io_chain_t &io_chain) case IO_BUFFER: case IO_PIPE: { + CAST_INIT(io_pipe_t *, io_pipe, io); /* If write_pipe_idx is 0, it means we're connecting to the read end (first pipe fd). If it's 1, we're connecting to the write end (second pipe fd). */ unsigned int write_pipe_idx = (io->is_input ? 0 : 1); /* @@ -253,20 +255,20 @@ static int handle_child_io(io_chain_t &io_chain) write_pipe?L"write":L"read", (io->io_mode == IO_BUFFER)?L"buffer":L"pipe", io->fd, - io->param1.pipe_fd[0], - io->param1.pipe_fd[1]); + io->pipe_fd[0], + io->pipe_fd[1]); */ - if (dup2(io->param1.pipe_fd[write_pipe_idx], io->fd) != io->fd) + if (dup2(io_pipe->pipe_fd[write_pipe_idx], io->fd) != io->fd) { debug_safe(1, LOCAL_PIPE_ERROR); safe_perror("dup2"); return -1; } - if (io->param1.pipe_fd[0] >= 0) - exec_close(io->param1.pipe_fd[0]); - if (io->param1.pipe_fd[1] >= 0) - exec_close(io->param1.pipe_fd[1]); + if (io_pipe->pipe_fd[0] >= 0) + exec_close(io_pipe->pipe_fd[0]); + if (io_pipe->pipe_fd[1] >= 0) + exec_close(io_pipe->pipe_fd[1]); break; } @@ -485,8 +487,9 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil case IO_BUFFER: case IO_PIPE: { + CAST_INIT(const io_pipe_t *, io_pipe, io.get()); unsigned int write_pipe_idx = (io->is_input ? 0 : 1); - int from_fd = io->param1.pipe_fd[write_pipe_idx]; + int from_fd = io_pipe->pipe_fd[write_pipe_idx]; int to_fd = io->fd; if (! err) err = posix_spawn_file_actions_adddup2(actions, from_fd, to_fd); @@ -495,14 +498,14 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil if (write_pipe_idx > 0) { if (! err) - err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]); + err = posix_spawn_file_actions_addclose(actions, io_pipe->pipe_fd[0]); if (! err) - err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[1]); + err = posix_spawn_file_actions_addclose(actions, io_pipe->pipe_fd[1]); } else { if (! err) - err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]); + err = posix_spawn_file_actions_addclose(actions, io_pipe->pipe_fd[0]); } break; diff --git a/proc.cpp b/proc.cpp index 2e6e32ee9..87c8f362f 100644 --- a/proc.cpp +++ b/proc.cpp @@ -869,10 +869,11 @@ static int select_try(job_t *j) for (size_t idx = 0; idx < j->io.size(); idx++) { - const io_data_t *d = j->io.at(idx).get(); - if (d->io_mode == IO_BUFFER) + const io_data_t *io = j->io.at(idx).get(); + if (io->io_mode == IO_BUFFER) { - int fd = d->param1.pipe_fd[0]; + CAST_INIT(const io_pipe_t *, io_pipe, io); + int fd = io_pipe->pipe_fd[0]; // fwprintf( stderr, L"fd %d on job %ls\n", fd, j->command ); FD_SET(fd, &fds); maxfd = maxi(maxfd, fd); @@ -924,7 +925,7 @@ static void read_try(job_t *j) char b[BUFFER_SIZE]; long l; - l=read_blocked(buff->param1.pipe_fd[0], + l=read_blocked(buff->pipe_fd[0], b, BUFFER_SIZE); if (l==0) { From 9808829ece19fce949a0accde6f2a0f4c4b2202b Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Tue, 15 Jan 2013 17:39:20 +0800 Subject: [PATCH 17/21] Make io_data_t pure virtual, its constructor protected --- io.cpp | 2 +- io.h | 31 +++++++++++++++---------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/io.cpp b/io.cpp index 4ec1d2bf4..14c48e1b1 100644 --- a/io.cpp +++ b/io.cpp @@ -51,7 +51,7 @@ Utilities for io redirection. #include "io.h" -void io_data_t::print() const +io_data_t::~io_data_t() { } diff --git a/io.h b/io.h index 5f3c1a678..a50c54e53 100644 --- a/io.h +++ b/io.h @@ -10,7 +10,7 @@ using std::tr1::shared_ptr; */ enum io_mode_t { - IO_INVALID, IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE + IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE }; /** Represents an FD redirection */ @@ -21,27 +21,26 @@ private: io_data_t(const io_data_t &rhs); void operator=(const io_data_t &rhs); -public: - /** Type of redirect */ - io_mode_t io_mode; - /** FD to redirect */ - int fd; - - virtual void print() const; - - /** Set to true if this is an input io redirection */ - bool is_input; - - io_data_t(io_mode_t m = IO_INVALID, int f=0) : +protected: + io_data_t(io_mode_t m, int f) : io_mode(m), fd(f), is_input(0) { } - virtual ~io_data_t() - { - } +public: + /** Type of redirect */ + io_mode_t io_mode; + /** FD to redirect */ + int fd; + + virtual void print() const = 0; + + /** Set to true if this is an input io redirection */ + bool is_input; + + virtual ~io_data_t() = 0; }; class io_close_t : public io_data_t From a63c0311bbd7ce2831a7b130f07b3a703d51201b Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Wed, 16 Jan 2013 11:27:50 +0800 Subject: [PATCH 18/21] Make io_buffer_t::out_buffer a raw pointer, initialize in io_buffer_t's constructor --- io.cpp | 2 +- io.h | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/io.cpp b/io.cpp index 14c48e1b1..6c42b6a33 100644 --- a/io.cpp +++ b/io.cpp @@ -133,7 +133,6 @@ io_buffer_t *io_buffer_t::create(bool is_input) { bool success = true; io_buffer_t *buffer_redirect = new io_buffer_t(is_input ? 0 : 1); - buffer_redirect->out_buffer_create(); buffer_redirect->is_input = is_input ? true : false; if (exec_pipe(buffer_redirect->pipe_fd) == -1) @@ -163,6 +162,7 @@ io_buffer_t *io_buffer_t::create(bool is_input) io_buffer_t::~io_buffer_t() { + delete out_buffer; /** If this is an input buffer, then io_read_buffer will not have been called, and we need to close the output fd as well. diff --git a/io.h b/io.h index a50c54e53..084202629 100644 --- a/io.h +++ b/io.h @@ -120,11 +120,11 @@ class io_buffer_t : public io_pipe_t { private: /** buffer to save output in */ - shared_ptr > out_buffer; + std::vector *out_buffer; io_buffer_t(int f): io_pipe_t(f), - out_buffer() + out_buffer(new std::vector) { io_mode = IO_BUFFER; } @@ -134,36 +134,26 @@ public: virtual ~io_buffer_t(); - /** Function to create the output buffer */ - void out_buffer_create() - { - out_buffer.reset(new std::vector); - } - /** Function to append to the buffer */ void out_buffer_append(const char *ptr, size_t count) { - assert(out_buffer.get() != NULL); out_buffer->insert(out_buffer->end(), ptr, ptr + count); } /** Function to get a pointer to the buffer */ char *out_buffer_ptr(void) { - assert(out_buffer.get() != NULL); return out_buffer->empty() ? NULL : &out_buffer->at(0); } const char *out_buffer_ptr(void) const { - assert(out_buffer.get() != NULL); return out_buffer->empty() ? NULL : &out_buffer->at(0); } /** Function to get the size of the buffer */ size_t out_buffer_size(void) const { - assert(out_buffer.get() != NULL); return out_buffer->size(); } From 57ef5289feb4f8551031cc1077df7c33be2180bb Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Wed, 16 Jan 2013 11:55:57 +0800 Subject: [PATCH 19/21] Make is_input a member of io_pipe_t --- exec.cpp | 36 +++++++++++++++++++----------------- io.cpp | 11 ++++++----- io.h | 17 +++++++---------- postfork.cpp | 4 ++-- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/exec.cpp b/exec.cpp index 9e63c3d11..d064cdd22 100644 --- a/exec.cpp +++ b/exec.cpp @@ -571,20 +571,24 @@ void exec(parser_t &parser, job_t *j) { shared_ptr &io = j->io.at(idx); - if ((io->io_mode == IO_BUFFER) && io->is_input) + if ((io->io_mode == IO_BUFFER)) { - /* - Input redirection - create a new gobetween process to take - care of buffering, save the redirection in input_redirect - */ - process_t *fake = new process_t(); - fake->type = INTERNAL_BUFFER; - fake->pipe_write_fd = 1; - j->first_process->pipe_read_fd = io->fd; - fake->next = j->first_process; - j->first_process = fake; - input_redirect = static_cast(io.get()); - break; + CAST_INIT(io_buffer_t *, io_buffer, io.get()); + if (io_buffer->is_input) + { + /* + Input redirection - create a new gobetween process to take + care of buffering, save the redirection in input_redirect + */ + process_t *fake = new process_t(); + fake->type = INTERNAL_BUFFER; + fake->pipe_write_fd = 1; + j->first_process->pipe_read_fd = io->fd; + fake->next = j->first_process; + j->first_process = fake; + input_redirect = io_buffer; + break; + } } } @@ -615,12 +619,10 @@ void exec(parser_t &parser, job_t *j) } - shared_ptr pipe_read(new io_pipe_t(0)); - pipe_read->is_input = 1; + shared_ptr pipe_read(new io_pipe_t(0, true)); pipe_read->pipe_fd[0] = pipe_read->pipe_fd[1] = -1; - shared_ptr pipe_write(new io_pipe_t(1)); - pipe_write->is_input = 0; + shared_ptr pipe_write(new io_pipe_t(1, false)); pipe_write->pipe_fd[0] = pipe_write->pipe_fd[1] = -1; j->io.push_back(pipe_write); diff --git a/io.cpp b/io.cpp index 6c42b6a33..241f89d91 100644 --- a/io.cpp +++ b/io.cpp @@ -72,12 +72,14 @@ void io_file_t::print() const void io_pipe_t::print() const { - fprintf(stderr, "pipe {%d, %d}\n", pipe_fd[0], pipe_fd[1]); + fprintf(stderr, "pipe {%d, %d} (input: %s)\n", pipe_fd[0], pipe_fd[1], + is_input ? "yes" : "no"); } void io_buffer_t::print() const { - fprintf(stderr, "buffer %p (size %lu)\n", out_buffer_ptr(), out_buffer_size()); + fprintf(stderr, "buffer %p (input: %s, size %lu)\n", out_buffer_ptr(), + is_input ? "yes" : "no", out_buffer_size()); } void io_buffer_t::read() @@ -132,8 +134,7 @@ void io_buffer_t::read() io_buffer_t *io_buffer_t::create(bool is_input) { bool success = true; - io_buffer_t *buffer_redirect = new io_buffer_t(is_input ? 0 : 1); - buffer_redirect->is_input = is_input ? true : false; + io_buffer_t *buffer_redirect = new io_buffer_t(is_input ? 0 : 1, is_input); if (exec_pipe(buffer_redirect->pipe_fd) == -1) { @@ -221,7 +222,7 @@ void io_print(const io_chain_t &chain) for (size_t i=0; i < chain.size(); i++) { const shared_ptr &io = chain.at(i); - fprintf(stderr, "\t%lu: fd:%d, input:%s, ", (unsigned long)i, io->fd, io->is_input ? "yes" : "no"); + fprintf(stderr, "\t%lu: fd:%d, ", (unsigned long)i, io->fd); io->print(); } } diff --git a/io.h b/io.h index 084202629..c9bcd36a3 100644 --- a/io.h +++ b/io.h @@ -24,8 +24,7 @@ private: protected: io_data_t(io_mode_t m, int f) : io_mode(m), - fd(f), - is_input(0) + fd(f) { } @@ -36,10 +35,6 @@ public: int fd; virtual void print() const = 0; - - /** Set to true if this is an input io redirection */ - bool is_input; - virtual ~io_data_t() = 0; }; @@ -106,12 +101,14 @@ class io_pipe_t : public io_data_t { public: int pipe_fd[2]; + bool is_input; virtual void print() const; - io_pipe_t(int f): + io_pipe_t(int f, bool i): io_data_t(IO_PIPE, f), - pipe_fd() + pipe_fd(), + is_input(i) { } }; @@ -122,8 +119,8 @@ private: /** buffer to save output in */ std::vector *out_buffer; - io_buffer_t(int f): - io_pipe_t(f), + io_buffer_t(int f, bool i): + io_pipe_t(f, i), out_buffer(new std::vector) { io_mode = IO_BUFFER; diff --git a/postfork.cpp b/postfork.cpp index 558805ab4..3fa3e8c47 100644 --- a/postfork.cpp +++ b/postfork.cpp @@ -248,7 +248,7 @@ static int handle_child_io(io_chain_t &io_chain) { CAST_INIT(io_pipe_t *, io_pipe, io); /* If write_pipe_idx is 0, it means we're connecting to the read end (first pipe fd). If it's 1, we're connecting to the write end (second pipe fd). */ - unsigned int write_pipe_idx = (io->is_input ? 0 : 1); + unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1); /* debug( 0, L"%ls %ls on fd %d (%d %d)", @@ -488,7 +488,7 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil case IO_PIPE: { CAST_INIT(const io_pipe_t *, io_pipe, io.get()); - unsigned int write_pipe_idx = (io->is_input ? 0 : 1); + unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1); int from_fd = io_pipe->pipe_fd[write_pipe_idx]; int to_fd = io->fd; if (! err) From a3b15b995e9448e1ed34b1a9d4d168abdf161b6e Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Thu, 17 Jan 2013 14:46:02 +0800 Subject: [PATCH 20/21] Make io_data_t::io_mode const A protected constructor is needed in io_pipe_t to let io_buffer_t override its io_mode. --- io.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/io.h b/io.h index c9bcd36a3..c463836b2 100644 --- a/io.h +++ b/io.h @@ -30,7 +30,7 @@ protected: public: /** Type of redirect */ - io_mode_t io_mode; + const io_mode_t io_mode; /** FD to redirect */ int fd; @@ -99,6 +99,14 @@ public: class io_pipe_t : public io_data_t { +protected: + io_pipe_t(io_mode_t m, int f, bool i): + io_data_t(m, f), + pipe_fd(), + is_input(i) + { + } + public: int pipe_fd[2]; bool is_input; @@ -120,10 +128,9 @@ private: std::vector *out_buffer; io_buffer_t(int f, bool i): - io_pipe_t(f, i), + io_pipe_t(IO_BUFFER, f, i), out_buffer(new std::vector) { - io_mode = IO_BUFFER; } public: From e0c858478ad564712d9b2a2799abff8496dcc55c Mon Sep 17 00:00:00 2001 From: Cheer Xiao Date: Thu, 17 Jan 2013 15:46:10 +0800 Subject: [PATCH 21/21] Revert "Make io_buffer_t::out_buffer a raw pointer, initialize in io_buffer_t's constructor" This reverts commit d48ffab9d67da48cf45c2f5560c21a767144545f. Conflicts: io.cpp io.h --- io.cpp | 2 +- io.h | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/io.cpp b/io.cpp index 241f89d91..dfda6e55a 100644 --- a/io.cpp +++ b/io.cpp @@ -135,6 +135,7 @@ io_buffer_t *io_buffer_t::create(bool is_input) { bool success = true; io_buffer_t *buffer_redirect = new io_buffer_t(is_input ? 0 : 1, is_input); + buffer_redirect->out_buffer_create(); if (exec_pipe(buffer_redirect->pipe_fd) == -1) { @@ -163,7 +164,6 @@ io_buffer_t *io_buffer_t::create(bool is_input) io_buffer_t::~io_buffer_t() { - delete out_buffer; /** If this is an input buffer, then io_read_buffer will not have been called, and we need to close the output fd as well. diff --git a/io.h b/io.h index c463836b2..bfe910e33 100644 --- a/io.h +++ b/io.h @@ -125,11 +125,11 @@ class io_buffer_t : public io_pipe_t { private: /** buffer to save output in */ - std::vector *out_buffer; + shared_ptr > out_buffer; io_buffer_t(int f, bool i): io_pipe_t(IO_BUFFER, f, i), - out_buffer(new std::vector) + out_buffer() { } @@ -138,26 +138,36 @@ public: virtual ~io_buffer_t(); + /** Function to create the output buffer */ + void out_buffer_create() + { + out_buffer.reset(new std::vector); + } + /** Function to append to the buffer */ void out_buffer_append(const char *ptr, size_t count) { + assert(out_buffer.get() != NULL); out_buffer->insert(out_buffer->end(), ptr, ptr + count); } /** Function to get a pointer to the buffer */ char *out_buffer_ptr(void) { + assert(out_buffer.get() != NULL); return out_buffer->empty() ? NULL : &out_buffer->at(0); } const char *out_buffer_ptr(void) const { + assert(out_buffer.get() != NULL); return out_buffer->empty() ? NULL : &out_buffer->at(0); } /** Function to get the size of the buffer */ size_t out_buffer_size(void) const { + assert(out_buffer.get() != NULL); return out_buffer->size(); }