1 ////////////////////////////////////////////////////////////////////////////////
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004-2009
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"
31 extern char** environ
;
34 ////////////////////////////////////////////////////////////////////////////////
39 ////////////////////////////////////////////////////////////////////////////////
40 // argument-vector related stuff
42 static void skip_white (const std::string
& command
, unsigned& i
)
44 while(i
< command
.size() && isspace(command
[i
]))
48 // get_argument is the main function for breaking a string down into separate command arguments
49 // it mimics the way shells break down a command into an argv[] and unescapes the escaped characters on the way
51 static std::string
get_argument (const std::string
& command
, unsigned& i
)
56 // as far as I know, there is only double-quoting and no escape character in DOS
57 // so, how do you include a double-quote in an argument???
60 for ( ; i
< command
.size(); i
++)
63 if (!dquote
&& isspace(ch
)) break;
80 for ( ; i
< command
.size(); i
++)
83 if (!squote
&& !dquote
&& !escaped
&& isspace(ch
)) break;
118 // this function performs the reverse of the above on a single argument
119 // it escapes special characters and quotes the argument if necessary ready for shell interpretation
121 static std::string
make_argument (const std::string
& arg
)
124 bool needs_quotes
= false;
126 for (unsigned i
= 0; i
< arg
.size(); i
++)
130 // set of characters requiring escapes
133 case '\\': case '\'': case '\"': case '`': case '(': case ')':
134 case '&': case '|': case '<': case '>': case '*': case '?': case '!':
139 // set of whitespace characters that force quoting
152 result
.insert(result
.begin(), '"');
158 static char* copy_string (const char* str
)
160 char* result
= new char[strlen(str
)+1];
165 ////////////////////////////////////////////////////////////////////////////////
167 arg_vector::arg_vector (void)
172 arg_vector::arg_vector (const arg_vector
& a
)
178 arg_vector::arg_vector (char** a
)
184 arg_vector::arg_vector (const std::string
& command
)
190 arg_vector::arg_vector (const char* command
)
196 arg_vector::~arg_vector (void)
201 arg_vector
& arg_vector::operator = (const arg_vector
& a
)
203 return *this = a
.m_argv
;
206 arg_vector
& arg_vector::operator = (char** argv
)
209 for (unsigned i
= 0; argv
[i
]; i
++)
210 operator += (argv
[i
]);
214 arg_vector
& arg_vector::operator = (const std::string
& command
)
217 for (unsigned i
= 0; i
< command
.size(); )
219 std::string argument
= get_argument(command
, i
);
220 operator += (argument
);
221 skip_white(command
, i
);
226 arg_vector
& arg_vector::operator = (const char* command
)
228 return operator = (std::string(command
));
231 arg_vector
& arg_vector::operator += (const std::string
& str
)
237 arg_vector
& arg_vector::operator -= (const std::string
& str
)
243 void arg_vector::insert (unsigned index
, const std::string
& str
) throw(std::out_of_range
)
245 if (index
> size()) throw std::out_of_range("arg_vector::insert");
246 // copy up to but not including index, then add the new argument, then copy the rest
247 char** new_argv
= new char*[size()+2];
249 for ( ; i
< index
; i
++)
250 new_argv
[i
] = copy_string(m_argv
[i
]);
251 new_argv
[index
] = copy_string(str
.c_str());
252 for ( ; i
< size(); i
++)
253 new_argv
[i
+1] = copy_string(m_argv
[i
]);
259 void arg_vector::clear (unsigned index
) throw(std::out_of_range
)
261 if (index
>= size()) throw std::out_of_range("arg_vector::clear");
262 // copy up to index, skip it, then copy the rest
263 char** new_argv
= new char*[size()];
265 for ( ; i
< index
; i
++)
266 new_argv
[i
] = copy_string(m_argv
[i
]);
268 for ( ; i
< size(); i
++)
269 new_argv
[i
-1] = copy_string(m_argv
[i
]);
275 void arg_vector::clear(void)
279 for (unsigned i
= 0; m_argv
[i
]; i
++)
286 unsigned arg_vector::size (void) const
295 arg_vector::operator char** (void) const
300 char** arg_vector::argv (void) const
305 char* arg_vector::operator [] (unsigned index
) const throw(std::out_of_range
)
307 if (index
>= size()) throw std::out_of_range("arg_vector::operator[]");
308 return m_argv
[index
];
311 char* arg_vector::argv0 (void) const throw(std::out_of_range
)
313 return operator [] (0);
316 std::string
arg_vector::image (void) const
319 for (unsigned i
= 0; i
< size(); i
++)
321 if (i
) result
+= ' ';
322 result
+= make_argument(m_argv
[i
]);
327 ////////////////////////////////////////////////////////////////////////////////
328 // environment-vector
330 // Windoze environment is a single string containing null-terminated
331 // name=value strings and the whole terminated by a null
333 // Unix environment is a null-terminated vector of pointers to null-terminated strings
335 ////////////////////////////////////////////////////////////////////////////////
336 // platform specifics
341 // Windows environment variables are case-insensitive and I do comparisons by converting to lowercase
342 static std::string
lowercase(const std::string
& val
)
344 std::string text
= val
;
345 for (unsigned i
= 0; i
< text
.size(); i
++)
346 text
[i
] = tolower(text
[i
]);
350 static unsigned envp_size(const char* envp
)
353 while (envp
[size
] || (size
> 0 && envp
[size
-1])) size
++;
358 static void envp_extract(std::string
& name
, std::string
& value
, const char* envp
, unsigned& envi
)
362 if (!envp
[envi
]) return;
363 // some special variables start with '=' so ensure at least one character in the name
364 name
+= envp
[envi
++];
365 while(envp
[envi
] != '=')
366 name
+= envp
[envi
++];
369 value
+= envp
[envi
++];
373 static void envp_append(const std::string
& name
, const std::string
& value
, char* envp
, unsigned& envi
)
375 for (unsigned i
= 0; i
< name
.size(); i
++)
376 envp
[envi
++] = name
[i
];
378 for (unsigned j
= 0; j
< value
.size(); j
++)
379 envp
[envi
++] = value
[j
];
384 static char* envp_copy(const char* envp
)
386 unsigned size
= envp_size(envp
);
387 char* result
= new char[size
];
395 envp_extract(name
, value
, envp
, i
);
396 envp_append(name
, value
, result
, j
);
401 static void envp_clear(char*& envp
)
410 static bool envp_equal(const std::string
& left
, const std::string
& right
)
412 return lowercase(left
) == lowercase(right
);
415 static bool envp_less(const std::string
& left
, const std::string
& right
)
417 return lowercase(left
) < lowercase(right
);
423 static unsigned envp_size(char* const* envp
)
426 while(envp
[size
]) size
++;
431 static void envp_extract(std::string
& name
, std::string
& value
, char* const* envp
, unsigned& envi
)
435 if (!envp
[envi
]) return;
437 while(envp
[envi
][i
] != '=')
438 name
+= envp
[envi
][i
++];
441 value
+= envp
[envi
][i
++];
445 static void envp_append(const std::string
& name
, const std::string
& value
, char** envp
, unsigned& envi
)
447 std::string entry
= name
+ "=" + value
;
448 envp
[envi
] = copy_string(entry
.c_str());
453 static char** envp_copy(char* const* envp
)
455 unsigned size
= envp_size(envp
);
456 char** result
= new char*[size
];
463 envp_extract(name
, value
, envp
, i
);
464 envp_append(name
, value
, result
, j
);
469 static void envp_clear(char**& envp
)
473 for (unsigned i
= 0; envp
[i
]; i
++)
480 static bool envp_equal(const std::string
& left
, const std::string
& right
)
482 return left
== right
;
485 static bool envp_less(const std::string
& left
, const std::string
& right
)
491 ////////////////////////////////////////////////////////////////////////////////
493 env_vector::env_vector(void)
496 char* env
= (char*)GetEnvironmentStringsA();
497 m_env
= envp_copy(env
);
498 FreeEnvironmentStringsA(env
);
500 m_env
= envp_copy(::environ
);
504 env_vector::env_vector (const env_vector
& a
)
510 env_vector::~env_vector (void)
515 env_vector
& env_vector::operator = (const env_vector
& a
)
518 m_env
= envp_copy(a
.m_env
);
522 void env_vector::clear(void)
527 void env_vector::add(const std::string
& name
, const std::string
& value
)
529 // the trick is to add the value in alphabetic order
530 // this is done by copying the existing environment string to a new
531 // string, inserting the new value when a name greater than it is found
532 unsigned size
= envp_size(m_env
);
534 unsigned new_size
= size
+ name
.size() + value
.size() + 2;
535 char* new_v
= new char[new_size
];
538 unsigned new_size
= size
+ 1;
539 char** new_v
= new char*[new_size
];
542 // now extract each name=value pair and check the ordering
548 std::string current_name
;
549 std::string current_value
;
550 envp_extract(current_name
, current_value
, m_env
, i
);
551 if (envp_equal(name
,current_name
))
553 // replace an existing value
554 envp_append(name
, value
, new_v
, j
);
556 else if (!added
&& envp_less(name
,current_name
))
558 // add the new value first, then the existing one
559 envp_append(name
, value
, new_v
, j
);
560 envp_append(current_name
, current_value
, new_v
, j
);
565 // just add the existing value
566 envp_append(current_name
, current_value
, new_v
, j
);
570 envp_append(name
, value
, new_v
, j
);
576 bool env_vector::remove (const std::string
& name
)
579 // this is done by copying the existing environment string to a new string, but excluding the specified name
580 unsigned size
= envp_size(m_env
);
582 char* new_v
= new char[size
];
585 char** new_v
= new char*[size
];
592 std::string current_name
;
593 std::string current_value
;
594 envp_extract(current_name
, current_value
, m_env
, i
);
595 if (envp_equal(name
,current_name
))
598 envp_append(current_name
, current_value
, new_v
, j
);
605 std::string
env_vector::operator [] (const std::string
& name
) const
610 std::string
env_vector::get (const std::string
& name
) const
615 std::string current_name
;
616 std::string current_value
;
617 envp_extract(current_name
, current_value
, m_env
, i
);
618 if (envp_equal(name
,current_name
))
619 return current_value
;
621 return std::string();
624 unsigned env_vector::size (void) const
631 std::string current_name
;
632 std::string current_value
;
633 envp_extract(current_name
, current_value
, m_env
, offset
);
644 std::pair
<std::string
,std::string
> env_vector::operator [] (unsigned index
) const throw(std::out_of_range
)
649 std::pair
<std::string
,std::string
> env_vector::get (unsigned index
) const throw(std::out_of_range
)
651 if (index
>= size()) throw std::out_of_range("arg_vector::get");
653 for (unsigned i
= 0; i
< index
; i
++)
655 std::string current_name
;
656 std::string current_value
;
657 envp_extract(current_name
, current_value
, m_env
, j
);
661 envp_extract(name
, value
, m_env
, j
);
662 return std::make_pair(name
,value
);
665 ENVIRON_TYPE
env_vector::envp (void) const
670 ////////////////////////////////////////////////////////////////////////////////
671 // Synchronous subprocess
672 // Win32 implementation mostly cribbed from MSDN examples and then made (much) more readable
673 // Unix implementation mostly from man pages and bitter experience
674 ////////////////////////////////////////////////////////////////////////////////
678 subprocess::subprocess(void)
691 subprocess::subprocess(void)
705 subprocess::~subprocess(void)
707 if (m_pid
.hProcess
!= 0)
713 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
714 CloseHandle(m_pid
.hThread
);
715 CloseHandle(m_pid
.hProcess
);
722 subprocess::~subprocess(void)
733 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
734 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
741 void subprocess::add_variable(const std::string
& name
, const std::string
& value
)
743 m_env
.add(name
, value
);
746 bool subprocess::remove_variable(const std::string
& name
)
748 return m_env
.remove(name
);
753 bool subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
754 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
757 // first create the pipes to be used to connect to the child stdin/out/err
758 // If no pipes requested, then connect to the parent stdin/out/err
759 // for some reason you have to create a pipe handle, then duplicate it
760 // This is not well explained in MSDN but seems to work
761 PIPE_TYPE parent_stdin
= 0;
763 parent_stdin
= GetStdHandle(STD_INPUT_HANDLE
);
767 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
768 CreatePipe(&parent_stdin
, &tmp
, &inherit_handles
, 0);
769 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_in
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
772 PIPE_TYPE parent_stdout
= 0;
774 parent_stdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
778 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
779 CreatePipe(&tmp
, &parent_stdout
, &inherit_handles
, 0);
780 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_out
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
783 PIPE_TYPE parent_stderr
= 0;
785 parent_stderr
= GetStdHandle(STD_ERROR_HANDLE
);
789 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
790 CreatePipe(&tmp
, &parent_stderr
, &inherit_handles
, 0);
791 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_err
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
794 // Now create the subprocess
795 // The horrible trick of creating a console window and hiding it seems to be required for the pipes to work
796 // Note that the child will inherit a copy of the pipe handles
797 STARTUPINFOA startup
= {sizeof(STARTUPINFO
),0,0,0,0,0,0,0,0,0,0,
798 STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
,SW_HIDE
,0,0,
799 parent_stdin
,parent_stdout
,parent_stderr
};
800 bool created
= CreateProcessA(path
.c_str(),(char*)argv
.image().c_str(),0,0,TRUE
,CREATE_SUSPENDED
,m_env
.envp(),0,&startup
,&m_pid
) != 0;
801 // close the parent copy of the pipe handles so that the pipes will be closed when the child releases them
802 if (connect_stdin
) CloseHandle(parent_stdin
);
803 if (connect_stdout
) CloseHandle(parent_stdout
);
804 if (connect_stderr
) CloseHandle(parent_stderr
);
807 m_err
= GetLastError();
815 m_job
= CreateJobObject(NULL
, NULL
);
816 AssignProcessToJobObject(m_job
, m_pid
.hProcess
);
817 ResumeThread(m_pid
.hThread
);
819 // The child process is now running so call the user's callback
820 // The convention is that the callback can return false, in which case this will kill the child (if its still running)
829 // wait for the child to finish
830 // TODO - kill the child if a timeout happens
831 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
832 DWORD exit_status
= 0;
833 if (!GetExitCodeProcess(m_pid
.hProcess
, &exit_status
))
835 m_err
= GetLastError();
838 else if (exit_status
!= 0)
840 m_status
= (int)exit_status
;
841 CloseHandle(m_pid
.hThread
);
842 CloseHandle(m_pid
.hProcess
);
851 bool subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
852 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
855 // first create the pipes to be used to connect to the child stdin/out/err
857 int stdin_pipe
[2] = {-1, -1};
861 int stdout_pipe
[2] = {-1, -1};
865 int stderr_pipe
[2] = {-1, -1};
869 // now create the subprocess
870 // In Unix, this is done by forking (creating two copies of the parent), then overwriting the child copy using exec
874 case -1: // failed to fork
878 ::close(stdin_pipe
[0]);
879 ::close(stdin_pipe
[1]);
883 ::close(stdout_pipe
[0]);
884 ::close(stdout_pipe
[1]);
888 ::close(stderr_pipe
[0]);
889 ::close(stderr_pipe
[1]);
895 // for each pipe, close the end of the duplicated pipe that is being used by the parent
896 // and connect the child's end of the pipe to the appropriate standard I/O device
899 ::close(stdin_pipe
[1]);
900 dup2(stdin_pipe
[0],STDIN_FILENO
);
904 ::close(stdout_pipe
[0]);
905 dup2(stdout_pipe
[1],STDOUT_FILENO
);
909 ::close(stderr_pipe
[0]);
910 dup2(stderr_pipe
[1],STDERR_FILENO
);
912 execve(path
.c_str(), argv
.argv(), m_env
.envp());
913 // will only ever get here if the exec() failed completely - *must* now exit the child process
914 // by using errno, the parent has some chance of diagnosing the cause of the problem
918 default: // in parent
920 // for each pipe, close the end of the duplicated pipe that is being used by the child
921 // and connect the parent's end of the pipe to the class members so that they are visible to the parent() callback
924 ::close(stdin_pipe
[0]);
925 m_child_in
= stdin_pipe
[1];
929 ::close(stdout_pipe
[1]);
930 m_child_out
= stdout_pipe
[0];
934 ::close(stderr_pipe
[1]);
935 m_child_err
= stderr_pipe
[0];
937 // call the user's callback
943 // close the pipes and wait for the child to finish
944 // wait exits on a signal which may be the child signalling its exit or may be an interrupt
951 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
952 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
954 // establish whether an error occurred
955 if (WIFSIGNALED(wait_status
))
958 m_status
= WTERMSIG(wait_status
);
961 else if (WIFEXITED(wait_status
))
963 m_status
= WEXITSTATUS(wait_status
);
976 bool subprocess::spawn(const std::string
& command_line
,
977 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
979 arg_vector arguments
= command_line
;
980 if (arguments
.size() == 0) return false;
981 std::string path
= path_lookup(arguments
.argv0());
982 if (path
.empty()) return false;
983 return spawn(path
, arguments
, connect_stdin
, connect_stdout
, connect_stderr
);
986 bool subprocess::callback(void)
993 bool subprocess::kill (void)
995 if (!m_pid
.hProcess
) return false;
999 if (!TerminateJobObject(m_job
, (UINT
)-1))
1001 m_err
= GetLastError();
1009 bool subprocess::kill (void)
1011 if (m_pid
== -1) return false;
1015 if (::kill(m_pid
, SIGINT
) == -1)
1027 int subprocess::write_stdin (std::string
& buffer
)
1029 if (m_child_in
== 0) return -1;
1030 // do a blocking write of the whole buffer
1032 if (!WriteFile(m_child_in
, buffer
.c_str(), (DWORD
)buffer
.size(), &bytes
, 0))
1034 m_err
= GetLastError();
1038 // now discard that part of the buffer that was written
1040 buffer
.erase(0, bytes
);
1046 int subprocess::write_stdin (std::string
& buffer
)
1048 if (m_child_in
== -1) return -1;
1049 // do a blocking write of the whole buffer
1050 int bytes
= write(m_child_in
, buffer
.c_str(), buffer
.size());
1057 // now discard that part of the buffer that was written
1059 buffer
.erase(0, bytes
);
1067 int subprocess::read_stdout (std::string
& buffer
)
1069 if (m_child_out
== 0) return -1;
1071 DWORD buffer_size
= 256;
1072 char* tmp
= new char[buffer_size
];
1073 if (!ReadFile(m_child_out
, tmp
, buffer_size
, &bytes
, 0))
1075 if (GetLastError() != ERROR_BROKEN_PIPE
)
1076 m_err
= GetLastError();
1088 buffer
.append(tmp
, bytes
);
1095 int subprocess::read_stdout (std::string
& buffer
)
1097 if (m_child_out
== -1) return -1;
1098 int buffer_size
= 256;
1099 char* tmp
= new char[buffer_size
];
1100 int bytes
= read(m_child_out
, tmp
, buffer_size
);
1115 buffer
.append(tmp
, bytes
);
1124 int subprocess::read_stderr(std::string
& buffer
)
1126 if (m_child_err
== 0) return -1;
1128 DWORD buffer_size
= 256;
1129 char* tmp
= new char[buffer_size
];
1130 if (!ReadFile(m_child_err
, tmp
, buffer_size
, &bytes
, 0))
1132 if (GetLastError() != ERROR_BROKEN_PIPE
)
1133 m_err
= GetLastError();
1145 buffer
.append(tmp
, bytes
);
1152 int subprocess::read_stderr (std::string
& buffer
)
1154 if (m_child_err
== -1) return -1;
1155 int buffer_size
= 256;
1156 char* tmp
= new char[buffer_size
];
1157 int bytes
= read(m_child_err
, tmp
, buffer_size
);
1172 buffer
.append(tmp
, bytes
);
1181 void subprocess::close_stdin (void)
1185 CloseHandle(m_child_in
);
1192 void subprocess::close_stdin (void)
1194 if (m_child_in
!= -1)
1196 ::close(m_child_in
);
1205 void subprocess::close_stdout (void)
1209 CloseHandle(m_child_out
);
1216 void subprocess::close_stdout (void)
1218 if (m_child_out
!= -1)
1220 ::close(m_child_out
);
1229 void subprocess::close_stderr (void)
1233 CloseHandle(m_child_err
);
1240 void subprocess::close_stderr (void)
1242 if (m_child_err
!= -1)
1244 ::close(m_child_err
);
1251 bool subprocess::error(void) const
1256 int subprocess::error_number(void) const
1263 std::string
subprocess::error_text(void) const
1265 if (m_err
== 0) return std::string();
1267 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_IGNORE_INSERTS
,
1270 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
1273 std::string result
= message
;
1275 // the error message is for some perverse reason newline terminated - remove this
1276 if (result
[result
.size()-1] == '\n')
1277 result
.erase(result
.end()-1);
1278 if (result
[result
.size()-1] == '\r')
1279 result
.erase(result
.end()-1);
1285 std::string
subprocess::error_text(void) const
1287 if (m_err
== 0) return std::string();
1288 char* text
= strerror(m_err
);
1289 if (text
) return std::string(text
);
1290 return "error number " + dformat("%d",m_err
);
1295 int subprocess::exit_status(void) const
1300 ////////////////////////////////////////////////////////////////////////////////
1301 // backtick subprocess and operations
1303 backtick_subprocess::backtick_subprocess(void) : subprocess()
1307 bool backtick_subprocess::callback(void)
1312 int read_size
= read_stdout(buffer
);
1313 if (read_size
< 0) break;
1319 bool backtick_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
)
1321 return subprocess::spawn(path
, argv
, false, true, false);
1324 bool backtick_subprocess::spawn(const std::string
& command_line
)
1326 return subprocess::spawn(command_line
, false, true, false);
1329 std::vector
<std::string
> backtick_subprocess::text(void) const
1331 std::vector
<std::string
> result
;
1332 // convert the raw text into a vector of strings, each corresponding to a line
1333 // in the process, strip out platform-specific line-endings
1334 for (unsigned i
= 0; i
< m_text
.size(); i
++)
1336 // handle any kind of line-ending - Dos, Unix or MacOS
1339 case '\xd': // carriage-return - optionally followed by linefeed
1341 // discard optional following linefeed
1342 if ((i
+1 < m_text
.size()) && (m_text
[i
+1] == '\xa'))
1344 // add a new line to the end of the vector
1345 result
.push_back(std::string());
1348 case '\xa': // linefeed
1350 // add a new line to the end of the vector
1351 result
.push_back(std::string());
1356 result
.back() += m_text
[i
];
1361 // tidy up - if the last line ended with a newline, the vector will end with an empty string - discard this
1362 if ((result
.size()) > 0 && result
.back().empty())
1363 result
.erase(result
.end()-1);
1367 std::vector
<std::string
> backtick(const std::string
& path
, const arg_vector
& argv
)
1369 backtick_subprocess sub
;
1370 sub
.spawn(path
, argv
);
1374 std::vector
<std::string
> backtick(const std::string
& command_line
)
1376 backtick_subprocess sub
;
1377 sub
.spawn(command_line
);
1381 ////////////////////////////////////////////////////////////////////////////////
1382 // Asynchronous subprocess
1386 async_subprocess::async_subprocess(void)
1399 async_subprocess::async_subprocess(void)
1413 async_subprocess::~async_subprocess(void)
1415 if (m_pid
.hProcess
!= 0)
1421 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
1422 CloseHandle(m_pid
.hThread
);
1423 CloseHandle(m_pid
.hProcess
);
1430 async_subprocess::~async_subprocess(void)
1440 int wait_status
= 0;
1441 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
1442 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
1449 void async_subprocess::set_error(int e
)
1454 void async_subprocess::add_variable(const std::string
& name
, const std::string
& value
)
1456 m_env
.add(name
, value
);
1459 bool async_subprocess::remove_variable(const std::string
& name
)
1461 return m_env
.remove(name
);
1466 bool async_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
1467 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1470 // first create the pipes to be used to connect to the child stdin/out/err
1471 // If no pipes requested, then connect to the parent stdin/out/err
1472 // for some reason you have to create a pipe handle, then duplicate it
1473 // This is not well explained in MSDN but seems to work
1474 PIPE_TYPE parent_stdin
= 0;
1476 parent_stdin
= GetStdHandle(STD_INPUT_HANDLE
);
1480 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1481 CreatePipe(&parent_stdin
, &tmp
, &inherit_handles
, 0);
1482 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_in
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1485 PIPE_TYPE parent_stdout
= 0;
1486 if (!connect_stdout
)
1487 parent_stdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
1491 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1492 CreatePipe(&tmp
, &parent_stdout
, &inherit_handles
, 0);
1493 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_out
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1496 PIPE_TYPE parent_stderr
= 0;
1497 if (!connect_stderr
)
1498 parent_stderr
= GetStdHandle(STD_ERROR_HANDLE
);
1502 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1503 CreatePipe(&tmp
, &parent_stderr
, &inherit_handles
, 0);
1504 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_err
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1507 // Now create the subprocess
1508 // The horrible trick of creating a console window and hiding it seems to be required for the pipes to work
1509 // Note that the child will inherit a copy of the pipe handles
1510 STARTUPINFOA startup
= {sizeof(STARTUPINFO
),0,0,0,0,0,0,0,0,0,0,
1511 STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
,SW_HIDE
,0,0,
1512 parent_stdin
,parent_stdout
,parent_stderr
};
1513 bool created
= CreateProcessA(path
.c_str(),(char*)argv
.image().c_str(),0,0,TRUE
,CREATE_SUSPENDED
,m_env
.envp(),0,&startup
,&m_pid
) != 0;
1514 // close the parent copy of the pipe handles so that the pipes will be closed when the child releases them
1515 if (connect_stdin
) CloseHandle(parent_stdin
);
1516 if (connect_stdout
) CloseHandle(parent_stdout
);
1517 if (connect_stderr
) CloseHandle(parent_stderr
);
1520 set_error(GetLastError());
1528 m_job
= CreateJobObject(NULL
, NULL
);
1529 AssignProcessToJobObject(m_job
, m_pid
.hProcess
);
1530 ResumeThread(m_pid
.hThread
);
1537 bool async_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
1538 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1541 // first create the pipes to be used to connect to the child stdin/out/err
1543 int stdin_pipe
[2] = {-1, -1};
1547 int stdout_pipe
[2] = {-1, -1};
1551 int stderr_pipe
[2] = {-1, -1};
1555 // now create the subprocess
1556 // In Unix, this is done by forking (creating two copies of the parent), then overwriting the child copy using exec
1560 case -1: // failed to fork
1564 ::close(stdin_pipe
[0]);
1565 ::close(stdin_pipe
[1]);
1569 ::close(stdout_pipe
[0]);
1570 ::close(stdout_pipe
[1]);
1574 ::close(stderr_pipe
[0]);
1575 ::close(stderr_pipe
[1]);
1579 case 0: // in child;
1581 // for each pipe, close the end of the duplicated pipe that is being used by the parent
1582 // and connect the child's end of the pipe to the appropriate standard I/O device
1585 ::close(stdin_pipe
[1]);
1586 dup2(stdin_pipe
[0],STDIN_FILENO
);
1590 ::close(stdout_pipe
[0]);
1591 dup2(stdout_pipe
[1],STDOUT_FILENO
);
1595 ::close(stderr_pipe
[0]);
1596 dup2(stderr_pipe
[1],STDERR_FILENO
);
1598 execve(path
.c_str(), argv
.argv(), m_env
.envp());
1599 // will only ever get here if the exec() failed completely - *must* now exit the child process
1600 // by using errno, the parent has some chance of diagnosing the cause of the problem
1604 default: // in parent
1606 // for each pipe, close the end of the duplicated pipe that is being used by the child
1607 // and connect the parent's end of the pipe to the class members so that they are visible to the parent() callback
1610 ::close(stdin_pipe
[0]);
1611 m_child_in
= stdin_pipe
[1];
1612 if (fcntl(m_child_in
, F_SETFL
, O_NONBLOCK
) == -1)
1620 ::close(stdout_pipe
[1]);
1621 m_child_out
= stdout_pipe
[0];
1622 if (fcntl(m_child_out
, F_SETFL
, O_NONBLOCK
) == -1)
1630 ::close(stderr_pipe
[1]);
1631 m_child_err
= stderr_pipe
[0];
1632 if (fcntl(m_child_err
, F_SETFL
, O_NONBLOCK
) == -1)
1646 bool async_subprocess::spawn(const std::string
& command_line
,
1647 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1649 arg_vector arguments
= command_line
;
1650 if (arguments
.size() == 0) return false;
1651 std::string path
= path_lookup(arguments
.argv0());
1652 if (path
.empty()) return false;
1653 return spawn(path
, arguments
, connect_stdin
, connect_stdout
, connect_stderr
);
1656 bool async_subprocess::callback(void)
1663 bool async_subprocess::tick(void)
1668 DWORD exit_status
= 0;
1669 if (!GetExitCodeProcess(m_pid
.hProcess
, &exit_status
))
1671 set_error(GetLastError());
1674 else if (exit_status
!= STILL_ACTIVE
)
1676 CloseHandle(m_pid
.hThread
);
1677 CloseHandle(m_pid
.hProcess
);
1682 m_status
= (int)exit_status
;
1688 bool async_subprocess::tick(void)
1693 int wait_status
= 0;
1694 int wait_ret_val
= waitpid(m_pid
, &wait_status
, WNOHANG
);
1695 if (wait_ret_val
== -1 && errno
!= EINTR
)
1700 else if (wait_ret_val
!= 0)
1702 // the only states that indicate a terminated child are WIFSIGNALLED and WIFEXITED
1703 if (WIFSIGNALED(wait_status
))
1705 // set_error(errno);
1706 m_status
= WTERMSIG(wait_status
);
1709 else if (WIFEXITED(wait_status
))
1712 m_status
= WEXITSTATUS(wait_status
);
1725 bool async_subprocess::kill(void)
1727 if (!m_pid
.hProcess
) return false;
1731 if (!TerminateJobObject(m_job
, (UINT
)-1))
1733 set_error(GetLastError());
1741 bool async_subprocess::kill(void)
1743 if (m_pid
== -1) return false;
1747 if (::kill(m_pid
, SIGINT
) == -1)
1759 int async_subprocess::write_stdin (std::string
& buffer
)
1761 if (m_child_in
== 0) return -1;
1762 // there doesn't seem to be a way of doing non-blocking writes under Windoze
1764 if (!WriteFile(m_child_in
, buffer
.c_str(), (DWORD
)buffer
.size(), &bytes
, 0))
1766 set_error(GetLastError());
1770 // now discard that part of the buffer that was written
1772 buffer
.erase(0, bytes
);
1778 int async_subprocess::write_stdin (std::string
& buffer
)
1780 if (m_child_in
== -1) return -1;
1781 // relies on the pipe being non-blocking
1782 // This does block under Windoze
1783 int bytes
= write(m_child_in
, buffer
.c_str(), buffer
.size());
1784 if (bytes
== -1 && errno
== EAGAIN
)
1791 // error on write - close the pipe and give up
1797 // now discard that part of the buffer that was written
1799 buffer
.erase(0, bytes
);
1807 int async_subprocess::read_stdout (std::string
& buffer
)
1809 if (m_child_out
== 0) return -1;
1810 // peek at the buffer to see how much data there is in the first place
1811 DWORD buffer_size
= 0;
1812 if (!PeekNamedPipe(m_child_out
, 0, 0, 0, &buffer_size
, 0))
1814 if (GetLastError() != ERROR_BROKEN_PIPE
)
1815 set_error(GetLastError());
1819 if (buffer_size
== 0) return 0;
1821 char* tmp
= new char[buffer_size
];
1822 if (!ReadFile(m_child_out
, tmp
, buffer_size
, &bytes
, 0))
1824 set_error(GetLastError());
1836 buffer
.append(tmp
, bytes
);
1843 int async_subprocess::read_stdout (std::string
& buffer
)
1845 if (m_child_out
== -1) return -1;
1846 // rely on the pipe being non-blocking
1847 int buffer_size
= 256;
1848 char* tmp
= new char[buffer_size
];
1849 int bytes
= read(m_child_out
, tmp
, buffer_size
);
1850 if (bytes
== -1 && errno
== EAGAIN
)
1872 buffer
.append(tmp
, bytes
);
1881 int async_subprocess::read_stderr (std::string
& buffer
)
1883 if (m_child_err
== 0) return -1;
1884 // peek at the buffer to see how much data there is in the first place
1885 DWORD buffer_size
= 0;
1886 if (!PeekNamedPipe(m_child_err
, 0, 0, 0, &buffer_size
, 0))
1888 if (GetLastError() != ERROR_BROKEN_PIPE
)
1889 set_error(GetLastError());
1893 if (buffer_size
== 0) return 0;
1895 char* tmp
= new char[buffer_size
];
1896 if (!ReadFile(m_child_err
, tmp
, buffer_size
, &bytes
, 0))
1898 set_error(GetLastError());
1910 buffer
.append(tmp
, bytes
);
1917 int async_subprocess::read_stderr (std::string
& buffer
)
1919 if (m_child_err
== -1) return -1;
1920 // rely on the pipe being non-blocking
1921 int buffer_size
= 256;
1922 char* tmp
= new char[buffer_size
];
1923 int bytes
= read(m_child_err
, tmp
, buffer_size
);
1924 if (bytes
== -1 && errno
== EAGAIN
)
1946 buffer
.append(tmp
, bytes
);
1955 void async_subprocess::close_stdin (void)
1959 CloseHandle(m_child_in
);
1966 void async_subprocess::close_stdin (void)
1968 if (m_child_in
!= -1)
1970 ::close(m_child_in
);
1979 void async_subprocess::close_stdout (void)
1983 CloseHandle(m_child_out
);
1990 void async_subprocess::close_stdout (void)
1992 if (m_child_out
!= -1)
1994 ::close(m_child_out
);
2003 void async_subprocess::close_stderr (void)
2007 CloseHandle(m_child_err
);
2014 void async_subprocess::close_stderr (void)
2016 if (m_child_err
!= -1)
2018 ::close(m_child_err
);
2025 bool async_subprocess::error(void) const
2030 int async_subprocess::error_number(void) const
2037 std::string
async_subprocess::error_text(void) const
2039 if (m_err
== 0) return std::string();
2041 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_IGNORE_INSERTS
,
2044 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
2047 std::string result
= message
;
2049 // the error message is for some perverse reason newline terminated - remove this
2050 if (result
[result
.size()-1] == '\n')
2051 result
.erase(result
.end()-1);
2052 if (result
[result
.size()-1] == '\r')
2053 result
.erase(result
.end()-1);
2059 std::string
async_subprocess::error_text(void) const
2061 if (m_err
== 0) return std::string();
2062 char* text
= strerror(m_err
);
2063 if (text
) return std::string(text
);
2064 return "error number " + dformat("%d",m_err
);
2069 int async_subprocess::exit_status(void) const
2074 ////////////////////////////////////////////////////////////////////////////////
2076 } // end namespace stlplus