1
/*************************************************
2
* Unix Command Execution Source File *
3
* (C) 1999-2007 The Botan Project *
4
*************************************************/
7
#define _XOPEN_SOURCE 500
10
#ifndef _XOPEN_SOURCE_EXTENDED
11
#define _XOPEN_SOURCE_EXTENDED 1
14
#include <botan/unix_cmd.h>
15
#include <botan/parsing.h>
17
#include <sys/types.h>
27
/*************************************************
28
* Attempt to execute the command *
29
************************************************/
30
void do_exec(const std::vector<std::string>& arg_list,
31
const std::vector<std::string>& paths)
33
const u32bit args = arg_list.size() - 1;
35
const char* arg1 = (args >= 1) ? arg_list[1].c_str() : 0;
36
const char* arg2 = (args >= 2) ? arg_list[2].c_str() : 0;
37
const char* arg3 = (args >= 3) ? arg_list[3].c_str() : 0;
38
const char* arg4 = (args >= 4) ? arg_list[4].c_str() : 0;
40
for(u32bit j = 0; j != paths.size(); j++)
42
const std::string full_path = paths[j] + "/" + arg_list[0];
43
const char* fsname = full_path.c_str();
44
execl(fsname, fsname, arg1, arg2, arg3, arg4, 0);
50
/*************************************************
51
* Local information about the pipe *
52
*************************************************/
57
pipe_wrapper() { fd = -1; pid = 0; }
60
/*************************************************
61
* Read from the pipe *
62
*************************************************/
63
u32bit DataSource_Command::read(byte buf[], u32bit length)
70
FD_SET(pipe->fd, &set);
74
tv.tv_usec = MAX_BLOCK_USECS;
77
if(select(pipe->fd + 1, &set, 0, 0, &tv) == 1)
79
if(FD_ISSET(pipe->fd, &set))
80
got = ::read(pipe->fd, buf, length);
92
/*************************************************
93
* Peek at the pipe contents *
94
*************************************************/
95
u32bit DataSource_Command::peek(byte[], u32bit, u32bit) const
98
throw Invalid_State("DataSource_Command: Cannot peek when out of data");
99
throw Stream_IO_Error("Cannot peek/seek on a command pipe");
102
/*************************************************
103
* Check if we reached EOF *
104
*************************************************/
105
bool DataSource_Command::end_of_data() const
107
return (pipe) ? false : true;
110
/*************************************************
111
* Return the Unix file descriptor of the pipe *
112
*************************************************/
113
int DataSource_Command::fd() const
120
/*************************************************
121
* Return a human-readable ID for this stream *
122
*************************************************/
123
std::string DataSource_Command::id() const
125
return "Unix command: " + arg_list[0];
128
/*************************************************
130
*************************************************/
131
void DataSource_Command::create_pipe(const std::string& path)
133
const std::vector<std::string> paths = split_on(path, ':');
135
bool found_something = false;
136
for(u32bit j = 0; j != paths.size(); j++)
138
const std::string full_path = paths[j] + "/" + arg_list[0];
139
if(access(full_path.c_str(), X_OK) == 0)
141
found_something = true;
149
if(::pipe(pipe_fd) != 0)
161
pipe = new pipe_wrapper;
162
pipe->fd = pipe_fd[0];
168
if(dup2(pipe_fd[1], STDOUT_FILENO) == -1)
170
if(close(pipe_fd[0]) != 0 || close(pipe_fd[1]) != 0)
172
if(close(STDERR_FILENO) != 0)
175
do_exec(arg_list, paths);
180
/*************************************************
181
* Shutdown the pipe *
182
*************************************************/
183
void DataSource_Command::shutdown_pipe()
187
pid_t reaped = waitpid(pipe->pid, 0, WNOHANG);
191
kill(pipe->pid, SIGTERM);
195
tv.tv_usec = KILL_WAIT;
196
select(0, 0, 0, 0, &tv);
198
reaped = waitpid(pipe->pid, 0, WNOHANG);
202
kill(pipe->pid, SIGKILL);
204
reaped = waitpid(pipe->pid, 0, 0);
215
/*************************************************
216
* DataSource_Command Constructor *
217
*************************************************/
218
DataSource_Command::DataSource_Command(const std::string& prog_and_args,
219
const std::string& path) :
220
MAX_BLOCK_USECS(100000), KILL_WAIT(10000)
222
arg_list = split_on(prog_and_args, ' ');
224
if(arg_list.size() == 0)
225
throw Invalid_Argument("DataSource_Command: No command given");
226
if(arg_list.size() > 5)
227
throw Invalid_Argument("DataSource_Command: Too many args");
233
/*************************************************
234
* DataSource_Command Destructor *
235
*************************************************/
236
DataSource_Command::~DataSource_Command()