1 ////////////////////////////////////////////////////////////////////////////////
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004 onwards
6 // License: BSD License, see ../docs/license.html
8 ////////////////////////////////////////////////////////////////////////////////
10 // Bug fix by Alistair Low: kill on Windows now kills grandchild processes as
11 // well as the child process. This is done using jobs - which has to be
12 // enabled by stating that the version of Windows is at least 5.0
13 #if defined(_WIN32) || defined(_WIN32_WCE)
14 #define _WIN32_WINNT 0x0500
17 #include "subprocesses.hpp"
18 #include "file_system.hpp"
19 #include "dprintf.hpp"
26 // missing declaration in Borland headers
27 LPTCH WINAPI
GetEnvironmentStringsA(void);
30 extern char** environ
;
38 ////////////////////////////////////////////////////////////////////////////////
43 ////////////////////////////////////////////////////////////////////////////////
44 // argument-vector related stuff
46 static void skip_white (const std::string
& command
, unsigned& i
)
48 while(i
< command
.size() && isspace(command
[i
]))
52 // get_argument is the main function for breaking a string down into separate command arguments
53 // it mimics the way shells break down a command into an argv[] and unescapes the escaped characters on the way
55 static std::string
get_argument (const std::string
& command
, unsigned& i
)
60 // as far as I know, there is only double-quoting and no escape character in DOS
61 // so, how do you include a double-quote in an argument???
64 for ( ; i
< command
.size(); i
++)
67 if (!dquote
&& isspace(ch
)) break;
84 for ( ; i
< command
.size(); i
++)
87 if (!squote
&& !dquote
&& !escaped
&& isspace(ch
)) break;
122 // this function performs the reverse of the above on a single argument
123 // it escapes special characters and quotes the argument if necessary ready for shell interpretation
125 static std::string
make_argument (const std::string
& arg
)
128 bool needs_quotes
= false;
130 for (unsigned i
= 0; i
< arg
.size(); i
++)
134 // set of characters requiring escapes
137 case '\\': case '\'': case '\"': case '`': case '(': case ')':
138 case '&': case '|': case '<': case '>': case '*': case '?': case '!':
143 // set of whitespace characters that force quoting
156 result
.insert(result
.begin(), '"');
162 static char* copy_string (const char* str
)
164 char* result
= new char[strlen(str
)+1];
169 ////////////////////////////////////////////////////////////////////////////////
171 arg_vector::arg_vector (void)
176 arg_vector::arg_vector (const arg_vector
& a
)
182 arg_vector::arg_vector (char** a
)
188 arg_vector::arg_vector (const std::string
& command
)
194 arg_vector::arg_vector (const char* command
)
200 arg_vector::~arg_vector (void)
205 arg_vector
& arg_vector::operator = (const arg_vector
& a
)
207 return *this = a
.m_argv
;
210 arg_vector
& arg_vector::operator = (char** argv
)
213 for (unsigned i
= 0; argv
[i
]; i
++)
214 operator += (argv
[i
]);
218 arg_vector
& arg_vector::operator = (const std::string
& command
)
221 for (unsigned i
= 0; i
< command
.size(); )
223 std::string argument
= get_argument(command
, i
);
224 operator += (argument
);
225 skip_white(command
, i
);
230 arg_vector
& arg_vector::operator = (const char* command
)
232 return operator = (std::string(command
));
235 arg_vector
& arg_vector::operator += (const std::string
& str
)
241 arg_vector
& arg_vector::operator -= (const std::string
& str
)
247 void arg_vector::insert (unsigned index
, const std::string
& str
) throw(std::out_of_range
)
249 if (index
> size()) throw std::out_of_range("arg_vector::insert");
250 // copy up to but not including index, then add the new argument, then copy the rest
251 char** new_argv
= new char*[size()+2];
253 for ( ; i
< index
; i
++)
254 new_argv
[i
] = copy_string(m_argv
[i
]);
255 new_argv
[index
] = copy_string(str
.c_str());
256 for ( ; i
< size(); i
++)
257 new_argv
[i
+1] = copy_string(m_argv
[i
]);
263 void arg_vector::clear (unsigned index
) throw(std::out_of_range
)
265 if (index
>= size()) throw std::out_of_range("arg_vector::clear");
266 // copy up to index, skip it, then copy the rest
267 char** new_argv
= new char*[size()];
269 for ( ; i
< index
; i
++)
270 new_argv
[i
] = copy_string(m_argv
[i
]);
272 for ( ; i
< size(); i
++)
273 new_argv
[i
-1] = copy_string(m_argv
[i
]);
279 void arg_vector::clear(void)
283 for (unsigned i
= 0; m_argv
[i
]; i
++)
290 unsigned arg_vector::size (void) const
299 arg_vector::operator char** (void) const
304 char** arg_vector::argv (void) const
309 char* arg_vector::operator [] (unsigned index
) const throw(std::out_of_range
)
311 if (index
>= size()) throw std::out_of_range("arg_vector::operator[]");
312 return m_argv
[index
];
315 char* arg_vector::argv0 (void) const throw(std::out_of_range
)
317 return operator [] (0);
320 std::string
arg_vector::image (void) const
323 for (unsigned i
= 0; i
< size(); i
++)
325 if (i
) result
+= ' ';
326 result
+= make_argument(m_argv
[i
]);
331 ////////////////////////////////////////////////////////////////////////////////
332 // environment-vector
334 // Windoze environment is a single string containing null-terminated
335 // name=value strings and the whole terminated by a null
337 // Unix environment is a null-terminated vector of pointers to null-terminated strings
339 ////////////////////////////////////////////////////////////////////////////////
340 // platform specifics
345 // Windows environment variables are case-insensitive and I do comparisons by converting to lowercase
346 static std::string
lowercase(const std::string
& val
)
348 std::string text
= val
;
349 for (unsigned i
= 0; i
< text
.size(); i
++)
350 text
[i
] = tolower(text
[i
]);
354 static unsigned envp_size(const char* envp
)
357 while (envp
[size
] || (size
> 0 && envp
[size
-1])) size
++;
362 static void envp_extract(std::string
& name
, std::string
& value
, const char* envp
, unsigned& envi
)
366 if (!envp
[envi
]) return;
367 // some special variables start with '=' so ensure at least one character in the name
368 name
+= envp
[envi
++];
369 while(envp
[envi
] != '=')
370 name
+= envp
[envi
++];
373 value
+= envp
[envi
++];
377 static void envp_append(const std::string
& name
, const std::string
& value
, char* envp
, unsigned& envi
)
379 for (unsigned i
= 0; i
< name
.size(); i
++)
380 envp
[envi
++] = name
[i
];
382 for (unsigned j
= 0; j
< value
.size(); j
++)
383 envp
[envi
++] = value
[j
];
388 static char* envp_copy(const char* envp
)
390 unsigned size
= envp_size(envp
);
391 char* result
= new char[size
];
399 envp_extract(name
, value
, envp
, i
);
400 envp_append(name
, value
, result
, j
);
405 static void envp_clear(char*& envp
)
414 static bool envp_equal(const std::string
& left
, const std::string
& right
)
416 return lowercase(left
) == lowercase(right
);
419 static bool envp_less(const std::string
& left
, const std::string
& right
)
421 return lowercase(left
) < lowercase(right
);
427 static unsigned envp_size(char* const* envp
)
430 while(envp
[size
]) size
++;
435 static void envp_extract(std::string
& name
, std::string
& value
, char* const* envp
, unsigned& envi
)
439 if (!envp
[envi
]) return;
441 while(envp
[envi
][i
] != '=')
442 name
+= envp
[envi
][i
++];
445 value
+= envp
[envi
][i
++];
449 static void envp_append(const std::string
& name
, const std::string
& value
, char** envp
, unsigned& envi
)
451 std::string entry
= name
+ "=" + value
;
452 envp
[envi
] = copy_string(entry
.c_str());
457 static char** envp_copy(char* const* envp
)
459 unsigned size
= envp_size(envp
);
460 char** result
= new char*[size
];
467 envp_extract(name
, value
, envp
, i
);
468 envp_append(name
, value
, result
, j
);
473 static void envp_clear(char**& envp
)
477 for (unsigned i
= 0; envp
[i
]; i
++)
484 static bool envp_equal(const std::string
& left
, const std::string
& right
)
486 return left
== right
;
489 static bool envp_less(const std::string
& left
, const std::string
& right
)
495 ////////////////////////////////////////////////////////////////////////////////
497 env_vector::env_vector(void)
500 char* env
= (char*)GetEnvironmentStringsA();
501 m_env
= envp_copy(env
);
502 FreeEnvironmentStringsA(env
);
504 m_env
= envp_copy(::environ
);
508 env_vector::env_vector (const env_vector
& a
)
514 env_vector::~env_vector (void)
519 env_vector
& env_vector::operator = (const env_vector
& a
)
522 m_env
= envp_copy(a
.m_env
);
526 void env_vector::clear(void)
531 void env_vector::add(const std::string
& name
, const std::string
& value
)
533 // the trick is to add the value in alphabetic order
534 // this is done by copying the existing environment string to a new
535 // string, inserting the new value when a name greater than it is found
536 unsigned size
= envp_size(m_env
);
538 unsigned new_size
= size
+ name
.size() + value
.size() + 2;
539 char* new_v
= new char[new_size
];
542 unsigned new_size
= size
+ 1;
543 char** new_v
= new char*[new_size
];
546 // now extract each name=value pair and check the ordering
552 std::string current_name
;
553 std::string current_value
;
554 envp_extract(current_name
, current_value
, m_env
, i
);
555 if (envp_equal(name
,current_name
))
557 // replace an existing value
558 envp_append(name
, value
, new_v
, j
);
560 else if (!added
&& envp_less(name
,current_name
))
562 // add the new value first, then the existing one
563 envp_append(name
, value
, new_v
, j
);
564 envp_append(current_name
, current_value
, new_v
, j
);
569 // just add the existing value
570 envp_append(current_name
, current_value
, new_v
, j
);
574 envp_append(name
, value
, new_v
, j
);
580 bool env_vector::remove (const std::string
& name
)
583 // this is done by copying the existing environment string to a new string, but excluding the specified name
584 unsigned size
= envp_size(m_env
);
586 char* new_v
= new char[size
];
589 char** new_v
= new char*[size
];
596 std::string current_name
;
597 std::string current_value
;
598 envp_extract(current_name
, current_value
, m_env
, i
);
599 if (envp_equal(name
,current_name
))
602 envp_append(current_name
, current_value
, new_v
, j
);
609 bool env_vector::present (const std::string
& name
) const
614 std::string current_name
;
615 std::string current_value
;
616 envp_extract(current_name
, current_value
, m_env
, i
);
617 if (envp_equal(name
,current_name
))
623 std::string
env_vector::operator [] (const std::string
& name
) const
628 std::string
env_vector::get (const std::string
& name
) const
633 std::string current_name
;
634 std::string current_value
;
635 envp_extract(current_name
, current_value
, m_env
, i
);
636 if (envp_equal(name
,current_name
))
637 return current_value
;
639 return std::string();
642 unsigned env_vector::size (void) const
649 std::string current_name
;
650 std::string current_value
;
651 envp_extract(current_name
, current_value
, m_env
, offset
);
662 std::pair
<std::string
,std::string
> env_vector::operator [] (unsigned index
) const throw(std::out_of_range
)
667 std::pair
<std::string
,std::string
> env_vector::get (unsigned index
) const throw(std::out_of_range
)
669 if (index
>= size()) throw std::out_of_range("arg_vector::get");
671 for (unsigned i
= 0; i
< index
; i
++)
673 std::string current_name
;
674 std::string current_value
;
675 envp_extract(current_name
, current_value
, m_env
, j
);
679 envp_extract(name
, value
, m_env
, j
);
680 return std::make_pair(name
,value
);
683 ENVIRON_TYPE
env_vector::envp (void) const
688 ////////////////////////////////////////////////////////////////////////////////
689 // Synchronous subprocess
690 // Win32 implementation mostly cribbed from MSDN examples and then made (much) more readable
691 // Unix implementation mostly from man pages and bitter experience
692 ////////////////////////////////////////////////////////////////////////////////
696 subprocess::subprocess(void)
709 subprocess::subprocess(void)
723 subprocess::~subprocess(void)
725 if (m_pid
.hProcess
!= 0)
731 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
732 CloseHandle(m_pid
.hThread
);
733 CloseHandle(m_pid
.hProcess
);
740 subprocess::~subprocess(void)
751 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
752 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
759 void subprocess::set_error(int e
)
764 void subprocess::add_variable(const std::string
& name
, const std::string
& value
)
766 m_env
.add(name
, value
);
769 bool subprocess::remove_variable(const std::string
& name
)
771 return m_env
.remove(name
);
774 const env_vector
& subprocess::get_variables(void) const
781 bool subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
782 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
785 // first create the pipes to be used to connect to the child stdin/out/err
786 // If no pipes requested, then connect to the parent stdin/out/err
787 // for some reason you have to create a pipe handle, then duplicate it
788 // This is not well explained in MSDN but seems to work
789 PIPE_TYPE parent_stdin
= 0;
791 parent_stdin
= GetStdHandle(STD_INPUT_HANDLE
);
795 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
796 CreatePipe(&parent_stdin
, &tmp
, &inherit_handles
, 0);
797 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_in
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
800 PIPE_TYPE parent_stdout
= 0;
802 parent_stdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
806 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
807 CreatePipe(&tmp
, &parent_stdout
, &inherit_handles
, 0);
808 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_out
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
811 PIPE_TYPE parent_stderr
= 0;
813 parent_stderr
= GetStdHandle(STD_ERROR_HANDLE
);
817 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
818 CreatePipe(&tmp
, &parent_stderr
, &inherit_handles
, 0);
819 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_err
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
822 // Now create the subprocess
823 // The horrible trick of creating a console window and hiding it seems to be required for the pipes to work
824 // Note that the child will inherit a copy of the pipe handles
825 STARTUPINFOA startup
= {sizeof(STARTUPINFO
),0,0,0,0,0,0,0,0,0,0,
826 STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
,SW_HIDE
,0,0,
827 parent_stdin
,parent_stdout
,parent_stderr
};
828 bool created
= CreateProcessA(path
.c_str(),(char*)argv
.image().c_str(),0,0,TRUE
,CREATE_SUSPENDED
,m_env
.envp(),0,&startup
,&m_pid
) != 0;
829 // close the parent copy of the pipe handles so that the pipes will be closed when the child releases them
830 if (connect_stdin
) CloseHandle(parent_stdin
);
831 if (connect_stdout
) CloseHandle(parent_stdout
);
832 if (connect_stderr
) CloseHandle(parent_stderr
);
835 set_error(GetLastError());
843 m_job
= CreateJobObject(NULL
, NULL
);
844 AssignProcessToJobObject(m_job
, m_pid
.hProcess
);
845 ResumeThread(m_pid
.hThread
);
847 // The child process is now running so call the user's callback
848 // The convention is that the callback can return false, in which case this will kill the child (if its still running)
857 // wait for the child to finish
858 // TODO - kill the child if a timeout happens
859 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
860 DWORD exit_status
= 0;
861 if (!GetExitCodeProcess(m_pid
.hProcess
, &exit_status
))
863 set_error(GetLastError());
866 else if (exit_status
!= 0)
868 m_status
= (int)exit_status
;
869 CloseHandle(m_pid
.hThread
);
870 CloseHandle(m_pid
.hProcess
);
879 bool subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
880 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
883 // first create the pipes to be used to connect to the child stdin/out/err
885 int stdin_pipe
[2] = {-1, -1};
887 if (::pipe(stdin_pipe
) != 0)
890 int stdout_pipe
[2] = {-1, -1};
892 if (::pipe(stdout_pipe
) != 0)
895 int stderr_pipe
[2] = {-1, -1};
897 if (::pipe(stderr_pipe
) != 0)
900 // now create the subprocess
901 // In Unix, this is done by forking (creating two copies of the parent), then overwriting the child copy using exec
905 case -1: // failed to fork
909 ::close(stdin_pipe
[0]);
910 ::close(stdin_pipe
[1]);
914 ::close(stdout_pipe
[0]);
915 ::close(stdout_pipe
[1]);
919 ::close(stderr_pipe
[0]);
920 ::close(stderr_pipe
[1]);
926 // for each pipe, close the end of the duplicated pipe that is being used by the parent
927 // and connect the child's end of the pipe to the appropriate standard I/O device
930 ::close(stdin_pipe
[1]);
931 ::dup2(stdin_pipe
[0],STDIN_FILENO
);
935 ::close(stdout_pipe
[0]);
936 ::dup2(stdout_pipe
[1],STDOUT_FILENO
);
940 ::close(stderr_pipe
[0]);
941 ::dup2(stderr_pipe
[1],STDERR_FILENO
);
943 execve(path
.c_str(), argv
.argv(), m_env
.envp());
944 // will only ever get here if the exec() failed completely - *must* now exit the child process
945 // by using errno, the parent has some chance of diagnosing the cause of the problem
949 default: // in parent
951 // for each pipe, close the end of the duplicated pipe that is being used by the child
952 // and connect the parent's end of the pipe to the class members so that they are visible to the parent() callback
955 ::close(stdin_pipe
[0]);
956 m_child_in
= stdin_pipe
[1];
960 ::close(stdout_pipe
[1]);
961 m_child_out
= stdout_pipe
[0];
965 ::close(stderr_pipe
[1]);
966 m_child_err
= stderr_pipe
[0];
968 // call the user's callback
974 // close the pipes and wait for the child to finish
975 // wait exits on a signal which may be the child signalling its exit or may be an interrupt
982 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
983 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
985 // establish whether an error occurred
986 if (WIFSIGNALED(wait_status
))
989 m_status
= WTERMSIG(wait_status
);
992 else if (WIFEXITED(wait_status
))
994 m_status
= WEXITSTATUS(wait_status
);
1007 bool subprocess::spawn(const std::string
& command_line
,
1008 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1010 arg_vector arguments
= command_line
;
1011 if (arguments
.size() == 0) return false;
1012 std::string path
= path_lookup(arguments
.argv0());
1013 if (path
.empty()) return false;
1014 return spawn(path
, arguments
, connect_stdin
, connect_stdout
, connect_stderr
);
1017 bool subprocess::callback(void)
1024 bool subprocess::kill (void)
1026 if (!m_pid
.hProcess
) return false;
1030 if (!TerminateJobObject(m_job
, (UINT
)-1))
1032 set_error(GetLastError());
1040 bool subprocess::kill (void)
1042 if (m_pid
== -1) return false;
1046 if (::kill(m_pid
, SIGINT
) == -1)
1058 int subprocess::write_stdin (std::string
& buffer
)
1060 if (m_child_in
== 0) return -1;
1061 // do a blocking write of the whole buffer
1063 if (!WriteFile(m_child_in
, buffer
.c_str(), (DWORD
)buffer
.size(), &bytes
, 0))
1065 set_error(GetLastError());
1069 // now discard that part of the buffer that was written
1071 buffer
.erase(0, bytes
);
1077 int subprocess::write_stdin (std::string
& buffer
)
1079 if (m_child_in
== -1) return -1;
1080 // do a blocking write of the whole buffer
1081 int bytes
= write(m_child_in
, buffer
.c_str(), buffer
.size());
1088 // now discard that part of the buffer that was written
1090 buffer
.erase(0, bytes
);
1098 int subprocess::read_stdout (std::string
& buffer
)
1100 if (m_child_out
== 0) return -1;
1102 DWORD buffer_size
= 256;
1103 char* tmp
= new char[buffer_size
];
1104 if (!ReadFile(m_child_out
, tmp
, buffer_size
, &bytes
, 0))
1106 if (GetLastError() != ERROR_BROKEN_PIPE
)
1107 set_error(GetLastError());
1119 buffer
.append(tmp
, bytes
);
1126 int subprocess::read_stdout (std::string
& buffer
)
1128 if (m_child_out
== -1) return -1;
1129 int buffer_size
= 256;
1130 char* tmp
= new char[buffer_size
];
1131 int bytes
= read(m_child_out
, tmp
, buffer_size
);
1146 buffer
.append(tmp
, bytes
);
1155 int subprocess::read_stderr(std::string
& buffer
)
1157 if (m_child_err
== 0) return -1;
1159 DWORD buffer_size
= 256;
1160 char* tmp
= new char[buffer_size
];
1161 if (!ReadFile(m_child_err
, tmp
, buffer_size
, &bytes
, 0))
1163 if (GetLastError() != ERROR_BROKEN_PIPE
)
1164 set_error(GetLastError());
1176 buffer
.append(tmp
, bytes
);
1183 int subprocess::read_stderr (std::string
& buffer
)
1185 if (m_child_err
== -1) return -1;
1186 int buffer_size
= 256;
1187 char* tmp
= new char[buffer_size
];
1188 int bytes
= read(m_child_err
, tmp
, buffer_size
);
1203 buffer
.append(tmp
, bytes
);
1212 void subprocess::close_stdin (void)
1216 CloseHandle(m_child_in
);
1223 void subprocess::close_stdin (void)
1225 if (m_child_in
!= -1)
1227 ::close(m_child_in
);
1236 void subprocess::close_stdout (void)
1240 CloseHandle(m_child_out
);
1247 void subprocess::close_stdout (void)
1249 if (m_child_out
!= -1)
1251 ::close(m_child_out
);
1260 void subprocess::close_stderr (void)
1264 CloseHandle(m_child_err
);
1271 void subprocess::close_stderr (void)
1273 if (m_child_err
!= -1)
1275 ::close(m_child_err
);
1282 bool subprocess::error(void) const
1287 int subprocess::error_number(void) const
1294 std::string
subprocess::error_text(void) const
1296 if (!error()) return std::string();
1298 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_IGNORE_INSERTS
,
1301 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
1304 std::string result
= message
;
1306 // the error message is for some perverse reason newline terminated - remove this
1307 if (result
[result
.size()-1] == '\n')
1308 result
.erase(result
.end()-1);
1309 if (result
[result
.size()-1] == '\r')
1310 result
.erase(result
.end()-1);
1316 std::string
subprocess::error_text(void) const
1318 if (!error()) return std::string();
1319 char* text
= strerror(m_err
);
1320 if (text
) return std::string(text
);
1321 return "error number " + dformat("%d",m_err
);
1326 int subprocess::exit_status(void) const
1331 ////////////////////////////////////////////////////////////////////////////////
1332 // backtick subprocess and operations
1334 backtick_subprocess::backtick_subprocess(void) : subprocess()
1338 bool backtick_subprocess::callback(void)
1343 int read_size
= read_stdout(buffer
);
1344 if (read_size
< 0) break;
1350 bool backtick_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
)
1352 return subprocess::spawn(path
, argv
, false, true, false);
1355 bool backtick_subprocess::spawn(const std::string
& command_line
)
1357 return subprocess::spawn(command_line
, false, true, false);
1360 std::vector
<std::string
> backtick_subprocess::text(void) const
1362 std::vector
<std::string
> result
;
1363 // convert the raw text into a vector of strings, each corresponding to a line
1364 // in the process, strip out platform-specific line-endings
1365 result
.push_back(std::string());
1366 for (unsigned i
= 0; i
< m_text
.size(); i
++)
1368 // handle any kind of line-ending - Dos, Unix or MacOS
1371 case '\xd': // carriage-return - optionally followed by linefeed
1373 // discard optional following linefeed
1374 if ((i
+1 < m_text
.size()) && (m_text
[i
+1] == '\xa'))
1376 // add a new line to the end of the vector
1377 result
.push_back(std::string());
1380 case '\xa': // linefeed
1382 // add a new line to the end of the vector
1383 result
.push_back(std::string());
1388 result
.back() += m_text
[i
];
1393 // tidy up - if the last line ended with a newline, the vector will end with an empty string - discard this
1394 if ((result
.size()) > 0 && result
.back().empty())
1395 result
.erase(result
.end()-1);
1399 std::vector
<std::string
> backtick(const std::string
& path
, const arg_vector
& argv
)
1401 backtick_subprocess sub
;
1402 sub
.spawn(path
, argv
);
1406 std::vector
<std::string
> backtick(const std::string
& command_line
)
1408 backtick_subprocess sub
;
1409 sub
.spawn(command_line
);
1413 ////////////////////////////////////////////////////////////////////////////////
1414 // Asynchronous subprocess
1418 async_subprocess::async_subprocess(void)
1431 async_subprocess::async_subprocess(void)
1445 async_subprocess::~async_subprocess(void)
1447 if (m_pid
.hProcess
!= 0)
1453 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
1454 CloseHandle(m_pid
.hThread
);
1455 CloseHandle(m_pid
.hProcess
);
1462 async_subprocess::~async_subprocess(void)
1472 int wait_status
= 0;
1473 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
1474 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
1481 void async_subprocess::set_error(int e
)
1486 void async_subprocess::add_variable(const std::string
& name
, const std::string
& value
)
1488 m_env
.add(name
, value
);
1491 bool async_subprocess::remove_variable(const std::string
& name
)
1493 return m_env
.remove(name
);
1496 const env_vector
& async_subprocess::get_variables(void) const
1503 bool async_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
1504 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1507 // first create the pipes to be used to connect to the child stdin/out/err
1508 // If no pipes requested, then connect to the parent stdin/out/err
1509 // for some reason you have to create a pipe handle, then duplicate it
1510 // This is not well explained in MSDN but seems to work
1511 PIPE_TYPE parent_stdin
= 0;
1513 parent_stdin
= GetStdHandle(STD_INPUT_HANDLE
);
1517 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1518 CreatePipe(&parent_stdin
, &tmp
, &inherit_handles
, 0);
1519 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_in
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1522 PIPE_TYPE parent_stdout
= 0;
1523 if (!connect_stdout
)
1524 parent_stdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
1528 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1529 CreatePipe(&tmp
, &parent_stdout
, &inherit_handles
, 0);
1530 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_out
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1533 PIPE_TYPE parent_stderr
= 0;
1534 if (!connect_stderr
)
1535 parent_stderr
= GetStdHandle(STD_ERROR_HANDLE
);
1539 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1540 CreatePipe(&tmp
, &parent_stderr
, &inherit_handles
, 0);
1541 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_err
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1544 // Now create the subprocess
1545 // The horrible trick of creating a console window and hiding it seems to be required for the pipes to work
1546 // Note that the child will inherit a copy of the pipe handles
1547 STARTUPINFOA startup
= {sizeof(STARTUPINFO
),0,0,0,0,0,0,0,0,0,0,
1548 STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
,SW_HIDE
,0,0,
1549 parent_stdin
,parent_stdout
,parent_stderr
};
1550 bool created
= CreateProcessA(path
.c_str(),(char*)argv
.image().c_str(),0,0,TRUE
,CREATE_SUSPENDED
,m_env
.envp(),0,&startup
,&m_pid
) != 0;
1551 // close the parent copy of the pipe handles so that the pipes will be closed when the child releases them
1552 if (connect_stdin
) CloseHandle(parent_stdin
);
1553 if (connect_stdout
) CloseHandle(parent_stdout
);
1554 if (connect_stderr
) CloseHandle(parent_stderr
);
1557 set_error(GetLastError());
1565 m_job
= CreateJobObject(NULL
, NULL
);
1566 AssignProcessToJobObject(m_job
, m_pid
.hProcess
);
1567 ResumeThread(m_pid
.hThread
);
1574 bool async_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
1575 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1578 // first create the pipes to be used to connect to the child stdin/out/err
1580 int stdin_pipe
[2] = {-1, -1};
1582 if (::pipe(stdin_pipe
) != 0)
1585 int stdout_pipe
[2] = {-1, -1};
1587 if (::pipe(stdout_pipe
) != 0)
1590 int stderr_pipe
[2] = {-1, -1};
1592 if (::pipe(stderr_pipe
) != 0)
1595 // now create the subprocess
1596 // In Unix, this is done by forking (creating two copies of the parent), then overwriting the child copy using exec
1600 case -1: // failed to fork
1604 ::close(stdin_pipe
[0]);
1605 ::close(stdin_pipe
[1]);
1609 ::close(stdout_pipe
[0]);
1610 ::close(stdout_pipe
[1]);
1614 ::close(stderr_pipe
[0]);
1615 ::close(stderr_pipe
[1]);
1619 case 0: // in child;
1621 // for each pipe, close the end of the duplicated pipe that is being used by the parent
1622 // and connect the child's end of the pipe to the appropriate standard I/O device
1625 ::close(stdin_pipe
[1]);
1626 ::dup2(stdin_pipe
[0],STDIN_FILENO
);
1630 ::close(stdout_pipe
[0]);
1631 ::dup2(stdout_pipe
[1],STDOUT_FILENO
);
1635 ::close(stderr_pipe
[0]);
1636 ::dup2(stderr_pipe
[1],STDERR_FILENO
);
1638 ::execve(path
.c_str(), argv
.argv(), m_env
.envp());
1639 // will only ever get here if the exec() failed completely - *must* now exit the child process
1640 // by using errno, the parent has some chance of diagnosing the cause of the problem
1644 default: // in parent
1646 // for each pipe, close the end of the duplicated pipe that is being used by the child
1647 // and connect the parent's end of the pipe to the class members so that they are visible to the parent() callback
1650 ::close(stdin_pipe
[0]);
1651 m_child_in
= stdin_pipe
[1];
1652 if (fcntl(m_child_in
, F_SETFL
, O_NONBLOCK
) == -1)
1660 ::close(stdout_pipe
[1]);
1661 m_child_out
= stdout_pipe
[0];
1662 if (fcntl(m_child_out
, F_SETFL
, O_NONBLOCK
) == -1)
1670 ::close(stderr_pipe
[1]);
1671 m_child_err
= stderr_pipe
[0];
1672 if (fcntl(m_child_err
, F_SETFL
, O_NONBLOCK
) == -1)
1686 bool async_subprocess::spawn(const std::string
& command_line
,
1687 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1689 arg_vector arguments
= command_line
;
1690 if (arguments
.size() == 0) return false;
1691 std::string path
= path_lookup(arguments
.argv0());
1692 if (path
.empty()) return false;
1693 return spawn(path
, arguments
, connect_stdin
, connect_stdout
, connect_stderr
);
1696 bool async_subprocess::callback(void)
1703 bool async_subprocess::tick(void)
1708 DWORD exit_status
= 0;
1709 if (!GetExitCodeProcess(m_pid
.hProcess
, &exit_status
))
1711 set_error(GetLastError());
1714 else if (exit_status
!= STILL_ACTIVE
)
1716 CloseHandle(m_pid
.hThread
);
1717 CloseHandle(m_pid
.hProcess
);
1722 m_status
= (int)exit_status
;
1728 bool async_subprocess::tick(void)
1733 int wait_status
= 0;
1734 int wait_ret_val
= waitpid(m_pid
, &wait_status
, WNOHANG
);
1735 if (wait_ret_val
== -1 && errno
!= EINTR
)
1740 else if (wait_ret_val
!= 0)
1742 // the only states that indicate a terminated child are WIFSIGNALLED and WIFEXITED
1743 if (WIFSIGNALED(wait_status
))
1745 // set_error(errno);
1746 m_status
= WTERMSIG(wait_status
);
1749 else if (WIFEXITED(wait_status
))
1752 m_status
= WEXITSTATUS(wait_status
);
1765 bool async_subprocess::kill(void)
1767 if (!m_pid
.hProcess
) return false;
1771 if (!TerminateJobObject(m_job
, (UINT
)-1))
1773 set_error(GetLastError());
1781 bool async_subprocess::kill(void)
1783 if (m_pid
== -1) return false;
1787 if (::kill(m_pid
, SIGINT
) == -1)
1799 int async_subprocess::write_stdin (std::string
& buffer
)
1801 if (m_child_in
== 0) return -1;
1802 // there doesn't seem to be a way of doing non-blocking writes under Windoze
1804 if (!WriteFile(m_child_in
, buffer
.c_str(), (DWORD
)buffer
.size(), &bytes
, 0))
1806 set_error(GetLastError());
1810 // now discard that part of the buffer that was written
1812 buffer
.erase(0, bytes
);
1818 int async_subprocess::write_stdin (std::string
& buffer
)
1820 if (m_child_in
== -1) return -1;
1821 // relies on the pipe being non-blocking
1822 // This does block under Windoze
1823 int bytes
= write(m_child_in
, buffer
.c_str(), buffer
.size());
1824 if (bytes
== -1 && errno
== EAGAIN
)
1831 // error on write - close the pipe and give up
1837 // now discard that part of the buffer that was written
1839 buffer
.erase(0, bytes
);
1847 int async_subprocess::read_stdout (std::string
& buffer
)
1849 if (m_child_out
== 0) return -1;
1850 // peek at the buffer to see how much data there is in the first place
1851 DWORD buffer_size
= 0;
1852 if (!PeekNamedPipe(m_child_out
, 0, 0, 0, &buffer_size
, 0))
1854 if (GetLastError() != ERROR_BROKEN_PIPE
)
1855 set_error(GetLastError());
1859 if (buffer_size
== 0) return 0;
1861 char* tmp
= new char[buffer_size
];
1862 if (!ReadFile(m_child_out
, tmp
, buffer_size
, &bytes
, 0))
1864 set_error(GetLastError());
1876 buffer
.append(tmp
, bytes
);
1883 int async_subprocess::read_stdout (std::string
& buffer
)
1885 if (m_child_out
== -1) return -1;
1886 // rely on the pipe being non-blocking
1887 int buffer_size
= 256;
1888 char* tmp
= new char[buffer_size
];
1889 int bytes
= read(m_child_out
, tmp
, buffer_size
);
1890 if (bytes
== -1 && errno
== EAGAIN
)
1912 buffer
.append(tmp
, bytes
);
1921 int async_subprocess::read_stderr (std::string
& buffer
)
1923 if (m_child_err
== 0) return -1;
1924 // peek at the buffer to see how much data there is in the first place
1925 DWORD buffer_size
= 0;
1926 if (!PeekNamedPipe(m_child_err
, 0, 0, 0, &buffer_size
, 0))
1928 if (GetLastError() != ERROR_BROKEN_PIPE
)
1929 set_error(GetLastError());
1933 if (buffer_size
== 0) return 0;
1935 char* tmp
= new char[buffer_size
];
1936 if (!ReadFile(m_child_err
, tmp
, buffer_size
, &bytes
, 0))
1938 set_error(GetLastError());
1950 buffer
.append(tmp
, bytes
);
1957 int async_subprocess::read_stderr (std::string
& buffer
)
1959 if (m_child_err
== -1) return -1;
1960 // rely on the pipe being non-blocking
1961 int buffer_size
= 256;
1962 char* tmp
= new char[buffer_size
];
1963 int bytes
= read(m_child_err
, tmp
, buffer_size
);
1964 if (bytes
== -1 && errno
== EAGAIN
)
1986 buffer
.append(tmp
, bytes
);
1995 void async_subprocess::close_stdin (void)
1999 CloseHandle(m_child_in
);
2006 void async_subprocess::close_stdin (void)
2008 if (m_child_in
!= -1)
2010 ::close(m_child_in
);
2019 void async_subprocess::close_stdout (void)
2023 CloseHandle(m_child_out
);
2030 void async_subprocess::close_stdout (void)
2032 if (m_child_out
!= -1)
2034 ::close(m_child_out
);
2043 void async_subprocess::close_stderr (void)
2047 CloseHandle(m_child_err
);
2054 void async_subprocess::close_stderr (void)
2056 if (m_child_err
!= -1)
2058 ::close(m_child_err
);
2065 bool async_subprocess::error(void) const
2070 int async_subprocess::error_number(void) const
2077 std::string
async_subprocess::error_text(void) const
2079 if (!error()) return std::string();
2081 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_IGNORE_INSERTS
,
2084 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
2087 std::string result
= message
;
2089 // the error message is for some perverse reason newline terminated - remove this
2090 if (result
[result
.size()-1] == '\n')
2091 result
.erase(result
.end()-1);
2092 if (result
[result
.size()-1] == '\r')
2093 result
.erase(result
.end()-1);
2099 std::string
async_subprocess::error_text(void) const
2101 if (!error()) return std::string();
2102 char* text
= strerror(m_err
);
2103 if (text
) return std::string(text
);
2104 return "error number " + dformat("%d",m_err
);
2109 int async_subprocess::exit_status(void) const
2114 ////////////////////////////////////////////////////////////////////////////////
2116 } // end namespace stlplus