2005-10-08 19:20:51 +08:00
|
|
|
#ifndef FISH_IO_H
|
|
|
|
#define FISH_IO_H
|
|
|
|
|
2012-03-07 16:54:01 +08:00
|
|
|
#include <vector>
|
2012-03-04 18:35:30 +08:00
|
|
|
#include <tr1/memory>
|
|
|
|
using std::tr1::shared_ptr;
|
|
|
|
|
2005-10-08 19:20:51 +08:00
|
|
|
/**
|
|
|
|
Describes what type of IO operation an io_data_t represents
|
|
|
|
*/
|
2013-01-01 01:11:46 +08:00
|
|
|
enum io_mode_t
|
2005-10-08 19:20:51 +08:00
|
|
|
{
|
2013-01-15 17:39:20 +08:00
|
|
|
IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE
|
2012-03-04 18:35:30 +08:00
|
|
|
};
|
2005-10-08 19:20:51 +08:00
|
|
|
|
|
|
|
/** Represents an FD redirection */
|
2012-03-04 18:35:30 +08:00
|
|
|
class io_data_t
|
2005-10-08 19:20:51 +08:00
|
|
|
{
|
2012-03-04 18:35:30 +08:00
|
|
|
private:
|
2013-01-07 23:04:55 +08:00
|
|
|
/* No assignment or copying allowed */
|
|
|
|
io_data_t(const io_data_t &rhs);
|
2012-08-06 04:24:33 +08:00
|
|
|
void operator=(const io_data_t &rhs);
|
2013-01-04 18:03:41 +08:00
|
|
|
|
2013-01-15 17:39:20 +08:00
|
|
|
protected:
|
|
|
|
io_data_t(io_mode_t m, int f) :
|
|
|
|
io_mode(m),
|
2013-01-16 11:55:57 +08:00
|
|
|
fd(f)
|
2013-01-15 17:39:20 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-03-04 18:35:30 +08:00
|
|
|
public:
|
2012-11-19 08:30:30 +08:00
|
|
|
/** Type of redirect */
|
2013-01-17 14:46:02 +08:00
|
|
|
const io_mode_t io_mode;
|
2012-11-19 08:30:30 +08:00
|
|
|
/** FD to redirect */
|
|
|
|
int fd;
|
|
|
|
|
2013-01-15 17:39:20 +08:00
|
|
|
virtual void print() const = 0;
|
|
|
|
virtual ~io_data_t() = 0;
|
2012-02-10 10:43:36 +08:00
|
|
|
};
|
2013-01-09 16:02:04 +08:00
|
|
|
|
|
|
|
class io_close_t : public io_data_t
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
io_close_t(int f) :
|
|
|
|
io_data_t(IO_CLOSE, f)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void print() const;
|
|
|
|
};
|
2013-01-15 15:37:33 +08:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
2013-01-15 16:18:03 +08:00
|
|
|
|
|
|
|
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. */
|
2013-01-20 02:59:43 +08:00
|
|
|
const char * const filename_cstr;
|
2013-01-15 16:18:03 +08:00
|
|
|
/** file creation flags to send to open */
|
|
|
|
int flags;
|
2013-01-21 10:34:18 +08:00
|
|
|
|
2013-01-15 16:18:03 +08:00
|
|
|
virtual void print() const;
|
|
|
|
|
2013-01-20 02:59:43 +08:00
|
|
|
io_file_t(int f, const wcstring &fname, int fl = 0) :
|
2013-01-15 16:18:03 +08:00
|
|
|
io_data_t(IO_FILE, f),
|
2013-01-20 02:59:43 +08:00
|
|
|
filename_cstr(wcs2str(fname)),
|
2013-01-15 16:18:03 +08:00
|
|
|
flags(fl)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~io_file_t()
|
|
|
|
{
|
|
|
|
free((void *)filename_cstr);
|
|
|
|
}
|
|
|
|
};
|
2005-10-08 19:20:51 +08:00
|
|
|
|
2013-01-15 17:31:36 +08:00
|
|
|
class io_pipe_t : public io_data_t
|
|
|
|
{
|
2013-01-17 14:46:02 +08:00
|
|
|
protected:
|
|
|
|
io_pipe_t(io_mode_t m, int f, bool i):
|
|
|
|
io_data_t(m, f),
|
|
|
|
pipe_fd(),
|
|
|
|
is_input(i)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-01-15 17:31:36 +08:00
|
|
|
public:
|
|
|
|
int pipe_fd[2];
|
2013-01-16 11:55:57 +08:00
|
|
|
bool is_input;
|
2013-01-15 17:31:36 +08:00
|
|
|
|
|
|
|
virtual void print() const;
|
|
|
|
|
2013-01-16 11:55:57 +08:00
|
|
|
io_pipe_t(int f, bool i):
|
2013-01-15 17:31:36 +08:00
|
|
|
io_data_t(IO_PIPE, f),
|
2013-01-16 11:55:57 +08:00
|
|
|
pipe_fd(),
|
|
|
|
is_input(i)
|
2013-01-15 17:31:36 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class io_buffer_t : public io_pipe_t
|
2013-01-15 16:44:31 +08:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
/** buffer to save output in */
|
2013-01-20 02:59:43 +08:00
|
|
|
std::vector<char> out_buffer;
|
2013-01-15 16:44:31 +08:00
|
|
|
|
2013-01-16 11:55:57 +08:00
|
|
|
io_buffer_t(int f, bool i):
|
2013-01-17 14:46:02 +08:00
|
|
|
io_pipe_t(IO_BUFFER, f, i),
|
2013-01-17 15:46:10 +08:00
|
|
|
out_buffer()
|
2013-01-15 16:44:31 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-01-15 17:07:30 +08:00
|
|
|
public:
|
|
|
|
virtual void print() const;
|
|
|
|
|
2013-01-16 11:30:18 +08:00
|
|
|
virtual ~io_buffer_t();
|
2013-01-15 17:02:46 +08:00
|
|
|
|
2013-01-15 16:44:31 +08:00
|
|
|
/** Function to append to the buffer */
|
|
|
|
void out_buffer_append(const char *ptr, size_t count)
|
|
|
|
{
|
2013-01-20 02:59:43 +08:00
|
|
|
out_buffer.insert(out_buffer.end(), ptr, ptr + count);
|
2013-01-15 16:44:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Function to get a pointer to the buffer */
|
|
|
|
char *out_buffer_ptr(void)
|
|
|
|
{
|
2013-01-20 02:59:43 +08:00
|
|
|
return out_buffer.empty() ? NULL : &out_buffer.at(0);
|
2013-01-15 16:44:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *out_buffer_ptr(void) const
|
|
|
|
{
|
2013-01-20 02:59:43 +08:00
|
|
|
return out_buffer.empty() ? NULL : &out_buffer.at(0);
|
2013-01-15 16:44:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Function to get the size of the buffer */
|
|
|
|
size_t out_buffer_size(void) const
|
|
|
|
{
|
2013-01-20 02:59:43 +08:00
|
|
|
return out_buffer.size();
|
2013-01-15 16:44:31 +08:00
|
|
|
}
|
2013-01-15 17:07:30 +08:00
|
|
|
|
2013-01-15 17:10:40 +08:00
|
|
|
/**
|
|
|
|
Close output pipe, and read from input pipe until eof.
|
|
|
|
*/
|
|
|
|
void read();
|
|
|
|
|
2013-01-15 17:07:30 +08:00
|
|
|
/**
|
|
|
|
Create a IO_BUFFER type io redirection, complete with a pipe and a
|
|
|
|
vector<char> 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);
|
2013-01-15 16:44:31 +08:00
|
|
|
};
|
|
|
|
|
2013-01-07 23:04:55 +08:00
|
|
|
class io_chain_t : public std::vector<shared_ptr<io_data_t> >
|
2012-11-19 08:30:30 +08:00
|
|
|
{
|
2012-08-15 15:57:56 +08:00
|
|
|
public:
|
|
|
|
io_chain_t();
|
2013-01-07 23:04:55 +08:00
|
|
|
io_chain_t(const shared_ptr<io_data_t> &);
|
2012-11-18 18:23:22 +08:00
|
|
|
|
2013-01-07 23:04:55 +08:00
|
|
|
void remove(const shared_ptr<const io_data_t> &element);
|
2012-11-18 18:23:22 +08:00
|
|
|
|
2013-01-07 23:04:55 +08:00
|
|
|
shared_ptr<const io_data_t> get_io_for_fd(int fd) const;
|
|
|
|
shared_ptr<io_data_t> get_io_for_fd(int fd);
|
2012-11-18 18:23:22 +08:00
|
|
|
|
2012-08-15 15:57:56 +08:00
|
|
|
};
|
2005-10-08 19:20:51 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
Remove the specified io redirection from the chain
|
|
|
|
*/
|
2013-01-07 23:04:55 +08:00
|
|
|
void io_remove(io_chain_t &list, const shared_ptr<const io_data_t> &element);
|
2005-10-08 19:20:51 +08:00
|
|
|
|
2012-08-15 15:57:56 +08:00
|
|
|
/** Destroys an io_chain */
|
|
|
|
void io_chain_destroy(io_chain_t &chain);
|
2005-10-08 19:20:51 +08:00
|
|
|
|
|
|
|
/**
|
2007-04-17 04:10:53 +08:00
|
|
|
Return the last io redirection in the chain for the specified file descriptor.
|
2005-10-08 19:20:51 +08:00
|
|
|
*/
|
2013-01-07 23:04:55 +08:00
|
|
|
shared_ptr<const io_data_t> io_chain_get(const io_chain_t &src, int fd);
|
|
|
|
shared_ptr<io_data_t> io_chain_get(io_chain_t &src, int fd);
|
2005-10-08 19:20:51 +08:00
|
|
|
|
|
|
|
|
2012-08-15 15:57:56 +08:00
|
|
|
/** Print debug information about the specified IO redirection chain to stderr. */
|
2012-11-19 08:30:30 +08:00
|
|
|
void io_print(const io_chain_t &chain);
|
2006-05-15 06:29:05 +08:00
|
|
|
|
2005-10-08 19:20:51 +08:00
|
|
|
#endif
|