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"
33 ////////////////////////////////////////////////////////////////////////////////
38 ////////////////////////////////////////////////////////////////////////////////
39 // argument-vector related stuff
41 static void skip_white (const std::string
& command
, unsigned& i
)
43 while(i
< command
.size() && isspace(command
[i
]))
47 // get_argument is the main function for breaking a string down into separate command arguments
48 // it mimics the way shells break down a command into an argv[] and unescapes the escaped characters on the way
50 static std::string
get_argument (const std::string
& command
, unsigned& i
)
55 // as far as I know, there is only double-quoting and no escape character in DOS
56 // so, how do you include a double-quote in an argument???
59 for ( ; i
< command
.size(); i
++)
62 if (!dquote
&& isspace(ch
)) break;
79 for ( ; i
< command
.size(); i
++)
82 if (!squote
&& !dquote
&& !escaped
&& isspace(ch
)) break;
117 // this function performs the reverse of the above on a single argument
118 // it escapes special characters and quotes the argument if necessary ready for shell interpretation
120 static std::string
make_argument (const std::string
& arg
)
123 bool needs_quotes
= false;
125 for (unsigned i
= 0; i
< arg
.size(); i
++)
129 // set of characters requiring escapes
132 case '\\': case '\'': case '\"': case '`': case '(': case ')':
133 case '&': case '|': case '<': case '>': case '*': case '?': case '!':
138 // set of whitespace characters that force quoting
151 result
.insert(result
.begin(), '"');
157 static char* copy_string (const char* str
)
159 char* result
= new char[strlen(str
)+1];
164 ////////////////////////////////////////////////////////////////////////////////
166 arg_vector::arg_vector (void)
171 arg_vector::arg_vector (const arg_vector
& a
)
177 arg_vector::arg_vector (char** a
)
183 arg_vector::arg_vector (const std::string
& command
)
189 arg_vector::arg_vector (const char* command
)
195 arg_vector::~arg_vector (void)
200 arg_vector
& arg_vector::operator = (const arg_vector
& a
)
202 return *this = a
.m_argv
;
205 arg_vector
& arg_vector::operator = (char** argv
)
208 for (unsigned i
= 0; argv
[i
]; i
++)
209 operator += (argv
[i
]);
213 arg_vector
& arg_vector::operator = (const std::string
& command
)
216 for (unsigned i
= 0; i
< command
.size(); )
218 std::string argument
= get_argument(command
, i
);
219 operator += (argument
);
220 skip_white(command
, i
);
225 arg_vector
& arg_vector::operator = (const char* command
)
227 return operator = (std::string(command
));
230 arg_vector
& arg_vector::operator += (const std::string
& str
)
236 arg_vector
& arg_vector::operator -= (const std::string
& str
)
242 void arg_vector::insert (unsigned index
, const std::string
& str
) throw(std::out_of_range
)
244 if (index
> size()) throw std::out_of_range("arg_vector::insert");
245 // copy up to but not including index, then add the new argument, then copy the rest
246 char** new_argv
= new char*[size()+2];
248 for ( ; i
< index
; i
++)
249 new_argv
[i
] = copy_string(m_argv
[i
]);
250 new_argv
[index
] = copy_string(str
.c_str());
251 for ( ; i
< size(); i
++)
252 new_argv
[i
+1] = copy_string(m_argv
[i
]);
258 void arg_vector::clear (unsigned index
) throw(std::out_of_range
)
260 if (index
>= size()) throw std::out_of_range("arg_vector::clear");
261 // copy up to index, skip it, then copy the rest
262 char** new_argv
= new char*[size()];
264 for ( ; i
< index
; i
++)
265 new_argv
[i
] = copy_string(m_argv
[i
]);
267 for ( ; i
< size(); i
++)
268 new_argv
[i
-1] = copy_string(m_argv
[i
]);
274 void arg_vector::clear(void)
278 for (unsigned i
= 0; m_argv
[i
]; i
++)
285 unsigned arg_vector::size (void) const
294 arg_vector::operator char** (void) const
299 char** arg_vector::argv (void) const
304 char* arg_vector::operator [] (unsigned index
) const throw(std::out_of_range
)
306 if (index
>= size()) throw std::out_of_range("arg_vector::operator[]");
307 return m_argv
[index
];
310 char* arg_vector::argv0 (void) const throw(std::out_of_range
)
312 return operator [] (0);
315 std::string
arg_vector::image (void) const
318 for (unsigned i
= 0; i
< size(); i
++)
320 if (i
) result
+= ' ';
321 result
+= make_argument(m_argv
[i
]);
326 ////////////////////////////////////////////////////////////////////////////////
327 // environment-vector
329 // Windoze environment is a single string containing null-terminated
330 // name=value strings and the whole terminated by a null
332 // Unix environment is a null-terminated vector of pointers to null-terminated strings
334 ////////////////////////////////////////////////////////////////////////////////
335 // platform specifics
340 // Windows environment variables are case-insensitive and I do comparisons by converting to lowercase
341 static std::string
lowercase(const std::string
& val
)
343 std::string text
= val
;
344 for (unsigned i
= 0; i
< text
.size(); i
++)
345 text
[i
] = tolower(text
[i
]);
349 static unsigned envp_size(const char* envp
)
352 while (envp
[size
] || (size
> 0 && envp
[size
-1])) size
++;
357 static void envp_extract(std::string
& name
, std::string
& value
, const char* envp
, unsigned& envi
)
361 if (!envp
[envi
]) return;
362 // some special variables start with '=' so ensure at least one character in the name
363 name
+= envp
[envi
++];
364 while(envp
[envi
] != '=')
365 name
+= envp
[envi
++];
368 value
+= envp
[envi
++];
372 static void envp_append(const std::string
& name
, const std::string
& value
, char* envp
, unsigned& envi
)
374 for (unsigned i
= 0; i
< name
.size(); i
++)
375 envp
[envi
++] = name
[i
];
377 for (unsigned j
= 0; j
< value
.size(); j
++)
378 envp
[envi
++] = value
[j
];
383 static char* envp_copy(const char* envp
)
385 unsigned size
= envp_size(envp
);
386 char* result
= new char[size
];
394 envp_extract(name
, value
, envp
, i
);
395 envp_append(name
, value
, result
, j
);
400 static void envp_clear(char*& envp
)
409 static bool envp_equal(const std::string
& left
, const std::string
& right
)
411 return lowercase(left
) == lowercase(right
);
414 static bool envp_less(const std::string
& left
, const std::string
& right
)
416 return lowercase(left
) < lowercase(right
);
422 extern char** environ
;
424 static unsigned envp_size(char* const* envp
)
427 while(envp
[size
]) size
++;
432 static void envp_extract(std::string
& name
, std::string
& value
, char* const* envp
, unsigned& envi
)
436 if (!envp
[envi
]) return;
438 while(envp
[envi
][i
] != '=')
439 name
+= envp
[envi
][i
++];
442 value
+= envp
[envi
][i
++];
446 static void envp_append(const std::string
& name
, const std::string
& value
, char** envp
, unsigned& envi
)
448 std::string entry
= name
+ "=" + value
;
449 envp
[envi
] = copy_string(entry
.c_str());
454 static char** envp_copy(char* const* envp
)
456 unsigned size
= envp_size(envp
);
457 char** result
= new char*[size
];
464 envp_extract(name
, value
, envp
, i
);
465 envp_append(name
, value
, result
, j
);
470 static void envp_clear(char**& envp
)
474 for (unsigned i
= 0; envp
[i
]; i
++)
481 static bool envp_equal(const std::string
& left
, const std::string
& right
)
483 return left
== right
;
486 static bool envp_less(const std::string
& left
, const std::string
& right
)
492 ////////////////////////////////////////////////////////////////////////////////
494 env_vector::env_vector(void)
497 char* env
= (char*)GetEnvironmentStringsA();
498 m_env
= envp_copy(env
);
499 FreeEnvironmentStringsA(env
);
501 m_env
= envp_copy(::environ
);
505 env_vector::env_vector (const env_vector
& a
)
511 env_vector::~env_vector (void)
516 env_vector
& env_vector::operator = (const env_vector
& a
)
519 m_env
= envp_copy(a
.m_env
);
523 void env_vector::clear(void)
528 void env_vector::add(const std::string
& name
, const std::string
& value
)
530 // the trick is to add the value in alphabetic order
531 // this is done by copying the existing environment string to a new
532 // string, inserting the new value when a name greater than it is found
533 unsigned size
= envp_size(m_env
);
535 unsigned new_size
= size
+ name
.size() + value
.size() + 2;
536 char* new_v
= new char[new_size
];
539 unsigned new_size
= size
+ 1;
540 char** new_v
= new char*[new_size
];
543 // now extract each name=value pair and check the ordering
549 std::string current_name
;
550 std::string current_value
;
551 envp_extract(current_name
, current_value
, m_env
, i
);
552 if (envp_equal(name
,current_name
))
554 // replace an existing value
555 envp_append(name
, value
, new_v
, j
);
557 else if (!added
&& envp_less(name
,current_name
))
559 // add the new value first, then the existing one
560 envp_append(name
, value
, new_v
, j
);
561 envp_append(current_name
, current_value
, new_v
, j
);
566 // just add the existing value
567 envp_append(current_name
, current_value
, new_v
, j
);
571 envp_append(name
, value
, new_v
, j
);
577 bool env_vector::remove (const std::string
& name
)
580 // this is done by copying the existing environment string to a new string, but excluding the specified name
581 unsigned size
= envp_size(m_env
);
583 char* new_v
= new char[size
];
586 char** new_v
= new char*[size
];
593 std::string current_name
;
594 std::string current_value
;
595 envp_extract(current_name
, current_value
, m_env
, i
);
596 if (envp_equal(name
,current_name
))
599 envp_append(current_name
, current_value
, new_v
, j
);
606 std::string
env_vector::operator [] (const std::string
& name
) const
611 std::string
env_vector::get (const std::string
& name
) const
616 std::string current_name
;
617 std::string current_value
;
618 envp_extract(current_name
, current_value
, m_env
, i
);
619 if (envp_equal(name
,current_name
))
620 return current_value
;
622 return std::string();
625 unsigned env_vector::size (void) const
632 std::string current_name
;
633 std::string current_value
;
634 envp_extract(current_name
, current_value
, m_env
, offset
);
645 std::pair
<std::string
,std::string
> env_vector::operator [] (unsigned index
) const throw(std::out_of_range
)
650 std::pair
<std::string
,std::string
> env_vector::get (unsigned index
) const throw(std::out_of_range
)
652 if (index
>= size()) throw std::out_of_range("arg_vector::get");
654 for (unsigned i
= 0; i
< index
; i
++)
656 std::string current_name
;
657 std::string current_value
;
658 envp_extract(current_name
, current_value
, m_env
, j
);
662 envp_extract(name
, value
, m_env
, j
);
663 return std::make_pair(name
,value
);
666 ENVIRON_TYPE
env_vector::envp (void) const
671 ////////////////////////////////////////////////////////////////////////////////
672 // Synchronous subprocess
673 // Win32 implementation mostly cribbed from MSDN examples and then made (much) more readable
674 // Unix implementation mostly from man pages and bitter experience
675 ////////////////////////////////////////////////////////////////////////////////
679 subprocess::subprocess(void)
692 subprocess::subprocess(void)
706 subprocess::~subprocess(void)
708 if (m_pid
.hProcess
!= 0)
714 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
715 CloseHandle(m_pid
.hThread
);
716 CloseHandle(m_pid
.hProcess
);
723 subprocess::~subprocess(void)
734 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
735 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
742 void subprocess::add_variable(const std::string
& name
, const std::string
& value
)
744 m_env
.add(name
, value
);
747 bool subprocess::remove_variable(const std::string
& name
)
749 return m_env
.remove(name
);
754 bool subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
755 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
758 // first create the pipes to be used to connect to the child stdin/out/err
759 // If no pipes requested, then connect to the parent stdin/out/err
760 // for some reason you have to create a pipe handle, then duplicate it
761 // This is not well explained in MSDN but seems to work
762 PIPE_TYPE parent_stdin
= 0;
764 parent_stdin
= GetStdHandle(STD_INPUT_HANDLE
);
768 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
769 CreatePipe(&parent_stdin
, &tmp
, &inherit_handles
, 0);
770 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_in
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
773 PIPE_TYPE parent_stdout
= 0;
775 parent_stdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
779 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
780 CreatePipe(&tmp
, &parent_stdout
, &inherit_handles
, 0);
781 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_out
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
784 PIPE_TYPE parent_stderr
= 0;
786 parent_stderr
= GetStdHandle(STD_ERROR_HANDLE
);
790 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
791 CreatePipe(&tmp
, &parent_stderr
, &inherit_handles
, 0);
792 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_err
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
795 // Now create the subprocess
796 // The horrible trick of creating a console window and hiding it seems to be required for the pipes to work
797 // Note that the child will inherit a copy of the pipe handles
798 STARTUPINFOA startup
= {sizeof(STARTUPINFO
),0,0,0,0,0,0,0,0,0,0,
799 STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
,SW_HIDE
,0,0,
800 parent_stdin
,parent_stdout
,parent_stderr
};
801 bool created
= CreateProcessA(path
.c_str(),(char*)argv
.image().c_str(),0,0,TRUE
,CREATE_SUSPENDED
,m_env
.envp(),0,&startup
,&m_pid
) != 0;
802 // close the parent copy of the pipe handles so that the pipes will be closed when the child releases them
803 if (connect_stdin
) CloseHandle(parent_stdin
);
804 if (connect_stdout
) CloseHandle(parent_stdout
);
805 if (connect_stderr
) CloseHandle(parent_stderr
);
808 m_err
= GetLastError();
816 m_job
= CreateJobObject(NULL
, NULL
);
817 AssignProcessToJobObject(m_job
, m_pid
.hProcess
);
818 ResumeThread(m_pid
.hThread
);
820 // The child process is now running so call the user's callback
821 // The convention is that the callback can return false, in which case this will kill the child (if its still running)
830 // wait for the child to finish
831 // TODO - kill the child if a timeout happens
832 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
833 DWORD exit_status
= 0;
834 if (!GetExitCodeProcess(m_pid
.hProcess
, &exit_status
))
836 m_err
= GetLastError();
839 else if (exit_status
!= 0)
841 m_status
= (int)exit_status
;
842 CloseHandle(m_pid
.hThread
);
843 CloseHandle(m_pid
.hProcess
);
852 bool subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
853 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
856 // first create the pipes to be used to connect to the child stdin/out/err
858 int stdin_pipe
[2] = {-1, -1};
862 int stdout_pipe
[2] = {-1, -1};
866 int stderr_pipe
[2] = {-1, -1};
870 // now create the subprocess
871 // In Unix, this is done by forking (creating two copies of the parent), then overwriting the child copy using exec
875 case -1: // failed to fork
879 ::close(stdin_pipe
[0]);
880 ::close(stdin_pipe
[1]);
884 ::close(stdout_pipe
[0]);
885 ::close(stdout_pipe
[1]);
889 ::close(stderr_pipe
[0]);
890 ::close(stderr_pipe
[1]);
896 // for each pipe, close the end of the duplicated pipe that is being used by the parent
897 // and connect the child's end of the pipe to the appropriate standard I/O device
900 ::close(stdin_pipe
[1]);
901 dup2(stdin_pipe
[0],STDIN_FILENO
);
905 ::close(stdout_pipe
[0]);
906 dup2(stdout_pipe
[1],STDOUT_FILENO
);
910 ::close(stderr_pipe
[0]);
911 dup2(stderr_pipe
[1],STDERR_FILENO
);
913 execve(path
.c_str(), argv
.argv(), m_env
.envp());
914 // will only ever get here if the exec() failed completely - *must* now exit the child process
915 // by using errno, the parent has some chance of diagnosing the cause of the problem
919 default: // in parent
921 // for each pipe, close the end of the duplicated pipe that is being used by the child
922 // and connect the parent's end of the pipe to the class members so that they are visible to the parent() callback
925 ::close(stdin_pipe
[0]);
926 m_child_in
= stdin_pipe
[1];
930 ::close(stdout_pipe
[1]);
931 m_child_out
= stdout_pipe
[0];
935 ::close(stderr_pipe
[1]);
936 m_child_err
= stderr_pipe
[0];
938 // call the user's callback
944 // close the pipes and wait for the child to finish
945 // wait exits on a signal which may be the child signalling its exit or may be an interrupt
952 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
953 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
955 // establish whether an error occurred
956 if (WIFSIGNALED(wait_status
))
959 m_status
= WTERMSIG(wait_status
);
962 else if (WIFEXITED(wait_status
))
964 m_status
= WEXITSTATUS(wait_status
);
977 bool subprocess::spawn(const std::string
& command_line
,
978 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
980 arg_vector arguments
= command_line
;
981 if (arguments
.size() == 0) return false;
982 std::string path
= path_lookup(arguments
.argv0());
983 if (path
.empty()) return false;
984 return spawn(path
, arguments
, connect_stdin
, connect_stdout
, connect_stderr
);
987 bool subprocess::callback(void)
994 bool subprocess::kill (void)
996 if (!m_pid
.hProcess
) return false;
1000 if (!TerminateJobObject(m_job
, (UINT
)-1))
1002 m_err
= GetLastError();
1010 bool subprocess::kill (void)
1012 if (m_pid
== -1) return false;
1016 if (::kill(m_pid
, SIGINT
) == -1)
1028 int subprocess::write_stdin (std::string
& buffer
)
1030 if (m_child_in
== 0) return -1;
1031 // do a blocking write of the whole buffer
1033 if (!WriteFile(m_child_in
, buffer
.c_str(), (DWORD
)buffer
.size(), &bytes
, 0))
1035 m_err
= GetLastError();
1039 // now discard that part of the buffer that was written
1041 buffer
.erase(0, bytes
);
1047 int subprocess::write_stdin (std::string
& buffer
)
1049 if (m_child_in
== -1) return -1;
1050 // do a blocking write of the whole buffer
1051 int bytes
= write(m_child_in
, buffer
.c_str(), buffer
.size());
1058 // now discard that part of the buffer that was written
1060 buffer
.erase(0, bytes
);
1068 int subprocess::read_stdout (std::string
& buffer
)
1070 if (m_child_out
== 0) return -1;
1072 DWORD buffer_size
= 256;
1073 char* tmp
= new char[buffer_size
];
1074 if (!ReadFile(m_child_out
, tmp
, buffer_size
, &bytes
, 0))
1076 if (GetLastError() != ERROR_BROKEN_PIPE
)
1077 m_err
= GetLastError();
1089 buffer
.append(tmp
, bytes
);
1096 int subprocess::read_stdout (std::string
& buffer
)
1098 if (m_child_out
== -1) return -1;
1099 int buffer_size
= 256;
1100 char* tmp
= new char[buffer_size
];
1101 int bytes
= read(m_child_out
, tmp
, buffer_size
);
1116 buffer
.append(tmp
, bytes
);
1125 int subprocess::read_stderr(std::string
& buffer
)
1127 if (m_child_err
== 0) return -1;
1129 DWORD buffer_size
= 256;
1130 char* tmp
= new char[buffer_size
];
1131 if (!ReadFile(m_child_err
, tmp
, buffer_size
, &bytes
, 0))
1133 if (GetLastError() != ERROR_BROKEN_PIPE
)
1134 m_err
= GetLastError();
1146 buffer
.append(tmp
, bytes
);
1153 int subprocess::read_stderr (std::string
& buffer
)
1155 if (m_child_err
== -1) return -1;
1156 int buffer_size
= 256;
1157 char* tmp
= new char[buffer_size
];
1158 int bytes
= read(m_child_err
, tmp
, buffer_size
);
1173 buffer
.append(tmp
, bytes
);
1182 void subprocess::close_stdin (void)
1186 CloseHandle(m_child_in
);
1193 void subprocess::close_stdin (void)
1195 if (m_child_in
!= -1)
1197 ::close(m_child_in
);
1206 void subprocess::close_stdout (void)
1210 CloseHandle(m_child_out
);
1217 void subprocess::close_stdout (void)
1219 if (m_child_out
!= -1)
1221 ::close(m_child_out
);
1230 void subprocess::close_stderr (void)
1234 CloseHandle(m_child_err
);
1241 void subprocess::close_stderr (void)
1243 if (m_child_err
!= -1)
1245 ::close(m_child_err
);
1252 bool subprocess::error(void) const
1257 int subprocess::error_number(void) const
1264 std::string
subprocess::error_text(void) const
1266 if (m_err
== 0) return std::string();
1268 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_IGNORE_INSERTS
,
1271 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
1274 std::string result
= message
;
1276 // the error message is for some perverse reason newline terminated - remove this
1277 if (result
[result
.size()-1] == '\n')
1278 result
.erase(result
.end()-1);
1279 if (result
[result
.size()-1] == '\r')
1280 result
.erase(result
.end()-1);
1286 std::string
subprocess::error_text(void) const
1288 if (m_err
== 0) return std::string();
1289 char* text
= strerror(m_err
);
1290 if (text
) return std::string(text
);
1291 return "error number " + dformat("%d",m_err
);
1296 int subprocess::exit_status(void) const
1301 ////////////////////////////////////////////////////////////////////////////////
1302 // backtick subprocess and operations
1304 backtick_subprocess::backtick_subprocess(void) : subprocess()
1308 bool backtick_subprocess::callback(void)
1313 int read_size
= read_stdout(buffer
);
1314 if (read_size
< 0) break;
1320 bool backtick_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
)
1322 return subprocess::spawn(path
, argv
, false, true, false);
1325 bool backtick_subprocess::spawn(const std::string
& command_line
)
1327 return subprocess::spawn(command_line
, false, true, false);
1330 std::vector
<std::string
> backtick_subprocess::text(void) const
1332 std::vector
<std::string
> result
;
1333 // convert the raw text into a vector of strings, each corresponding to a line
1334 // in the process, strip out platform-specific line-endings
1335 for (unsigned i
= 0; i
< m_text
.size(); i
++)
1337 // handle any kind of line-ending - Dos, Unix or MacOS
1340 case '\xd': // carriage-return - optionally followed by linefeed
1342 // discard optional following linefeed
1343 if ((i
+1 < m_text
.size()) && (m_text
[i
+1] == '\xa'))
1345 // add a new line to the end of the vector
1346 result
.push_back(std::string());
1349 case '\xa': // linefeed
1351 // add a new line to the end of the vector
1352 result
.push_back(std::string());
1357 result
.back() += m_text
[i
];
1362 // tidy up - if the last line ended with a newline, the vector will end with an empty string - discard this
1363 if ((result
.size()) > 0 && result
.back().empty())
1364 result
.erase(result
.end()-1);
1368 std::vector
<std::string
> backtick(const std::string
& path
, const arg_vector
& argv
)
1370 backtick_subprocess sub
;
1371 sub
.spawn(path
, argv
);
1375 std::vector
<std::string
> backtick(const std::string
& command_line
)
1377 backtick_subprocess sub
;
1378 sub
.spawn(command_line
);
1382 ////////////////////////////////////////////////////////////////////////////////
1383 // Asynchronous subprocess
1387 async_subprocess::async_subprocess(void)
1400 async_subprocess::async_subprocess(void)
1414 async_subprocess::~async_subprocess(void)
1416 if (m_pid
.hProcess
!= 0)
1422 WaitForSingleObject(m_pid
.hProcess
, INFINITE
);
1423 CloseHandle(m_pid
.hThread
);
1424 CloseHandle(m_pid
.hProcess
);
1431 async_subprocess::~async_subprocess(void)
1441 int wait_status
= 0;
1442 int wait_ret_val
= waitpid(m_pid
, &wait_status
, 0);
1443 if (wait_ret_val
!= -1 || errno
!= EINTR
) break;
1450 void async_subprocess::set_error(int e
)
1455 void async_subprocess::add_variable(const std::string
& name
, const std::string
& value
)
1457 m_env
.add(name
, value
);
1460 bool async_subprocess::remove_variable(const std::string
& name
)
1462 return m_env
.remove(name
);
1467 bool async_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
1468 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1471 // first create the pipes to be used to connect to the child stdin/out/err
1472 // If no pipes requested, then connect to the parent stdin/out/err
1473 // for some reason you have to create a pipe handle, then duplicate it
1474 // This is not well explained in MSDN but seems to work
1475 PIPE_TYPE parent_stdin
= 0;
1477 parent_stdin
= GetStdHandle(STD_INPUT_HANDLE
);
1481 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1482 CreatePipe(&parent_stdin
, &tmp
, &inherit_handles
, 0);
1483 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_in
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1486 PIPE_TYPE parent_stdout
= 0;
1487 if (!connect_stdout
)
1488 parent_stdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
1492 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1493 CreatePipe(&tmp
, &parent_stdout
, &inherit_handles
, 0);
1494 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_out
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1497 PIPE_TYPE parent_stderr
= 0;
1498 if (!connect_stderr
)
1499 parent_stderr
= GetStdHandle(STD_ERROR_HANDLE
);
1503 SECURITY_ATTRIBUTES inherit_handles
= {sizeof(SECURITY_ATTRIBUTES
), 0, TRUE
};
1504 CreatePipe(&tmp
, &parent_stderr
, &inherit_handles
, 0);
1505 DuplicateHandle(GetCurrentProcess(), tmp
, GetCurrentProcess(), &m_child_err
, 0, FALSE
, DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
);
1508 // Now create the subprocess
1509 // The horrible trick of creating a console window and hiding it seems to be required for the pipes to work
1510 // Note that the child will inherit a copy of the pipe handles
1511 STARTUPINFOA startup
= {sizeof(STARTUPINFO
),0,0,0,0,0,0,0,0,0,0,
1512 STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
,SW_HIDE
,0,0,
1513 parent_stdin
,parent_stdout
,parent_stderr
};
1514 bool created
= CreateProcessA(path
.c_str(),(char*)argv
.image().c_str(),0,0,TRUE
,CREATE_SUSPENDED
,m_env
.envp(),0,&startup
,&m_pid
) != 0;
1515 // close the parent copy of the pipe handles so that the pipes will be closed when the child releases them
1516 if (connect_stdin
) CloseHandle(parent_stdin
);
1517 if (connect_stdout
) CloseHandle(parent_stdout
);
1518 if (connect_stderr
) CloseHandle(parent_stderr
);
1521 set_error(GetLastError());
1529 m_job
= CreateJobObject(NULL
, NULL
);
1530 AssignProcessToJobObject(m_job
, m_pid
.hProcess
);
1531 ResumeThread(m_pid
.hThread
);
1538 bool async_subprocess::spawn(const std::string
& path
, const arg_vector
& argv
,
1539 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1542 // first create the pipes to be used to connect to the child stdin/out/err
1544 int stdin_pipe
[2] = {-1, -1};
1548 int stdout_pipe
[2] = {-1, -1};
1552 int stderr_pipe
[2] = {-1, -1};
1556 // now create the subprocess
1557 // In Unix, this is done by forking (creating two copies of the parent), then overwriting the child copy using exec
1561 case -1: // failed to fork
1565 ::close(stdin_pipe
[0]);
1566 ::close(stdin_pipe
[1]);
1570 ::close(stdout_pipe
[0]);
1571 ::close(stdout_pipe
[1]);
1575 ::close(stderr_pipe
[0]);
1576 ::close(stderr_pipe
[1]);
1580 case 0: // in child;
1582 // for each pipe, close the end of the duplicated pipe that is being used by the parent
1583 // and connect the child's end of the pipe to the appropriate standard I/O device
1586 ::close(stdin_pipe
[1]);
1587 dup2(stdin_pipe
[0],STDIN_FILENO
);
1591 ::close(stdout_pipe
[0]);
1592 dup2(stdout_pipe
[1],STDOUT_FILENO
);
1596 ::close(stderr_pipe
[0]);
1597 dup2(stderr_pipe
[1],STDERR_FILENO
);
1599 execve(path
.c_str(), argv
.argv(), m_env
.envp());
1600 // will only ever get here if the exec() failed completely - *must* now exit the child process
1601 // by using errno, the parent has some chance of diagnosing the cause of the problem
1605 default: // in parent
1607 // for each pipe, close the end of the duplicated pipe that is being used by the child
1608 // and connect the parent's end of the pipe to the class members so that they are visible to the parent() callback
1611 ::close(stdin_pipe
[0]);
1612 m_child_in
= stdin_pipe
[1];
1613 if (fcntl(m_child_in
, F_SETFL
, O_NONBLOCK
) == -1)
1621 ::close(stdout_pipe
[1]);
1622 m_child_out
= stdout_pipe
[0];
1623 if (fcntl(m_child_out
, F_SETFL
, O_NONBLOCK
) == -1)
1631 ::close(stderr_pipe
[1]);
1632 m_child_err
= stderr_pipe
[0];
1633 if (fcntl(m_child_err
, F_SETFL
, O_NONBLOCK
) == -1)
1647 bool async_subprocess::spawn(const std::string
& command_line
,
1648 bool connect_stdin
, bool connect_stdout
, bool connect_stderr
)
1650 arg_vector arguments
= command_line
;
1651 if (arguments
.size() == 0) return false;
1652 std::string path
= path_lookup(arguments
.argv0());
1653 if (path
.empty()) return false;
1654 return spawn(path
, arguments
, connect_stdin
, connect_stdout
, connect_stderr
);
1657 bool async_subprocess::callback(void)
1664 bool async_subprocess::tick(void)
1669 DWORD exit_status
= 0;
1670 if (!GetExitCodeProcess(m_pid
.hProcess
, &exit_status
))
1672 set_error(GetLastError());
1675 else if (exit_status
!= STILL_ACTIVE
)
1677 CloseHandle(m_pid
.hThread
);
1678 CloseHandle(m_pid
.hProcess
);
1683 m_status
= (int)exit_status
;
1689 bool async_subprocess::tick(void)
1694 int wait_status
= 0;
1695 int wait_ret_val
= waitpid(m_pid
, &wait_status
, WNOHANG
);
1696 if (wait_ret_val
== -1 && errno
!= EINTR
)
1701 else if (wait_ret_val
!= 0)
1703 // the only states that indicate a terminated child are WIFSIGNALLED and WIFEXITED
1704 if (WIFSIGNALED(wait_status
))
1706 // set_error(errno);
1707 m_status
= WTERMSIG(wait_status
);
1710 else if (WIFEXITED(wait_status
))
1713 m_status
= WEXITSTATUS(wait_status
);
1726 bool async_subprocess::kill(void)
1728 if (!m_pid
.hProcess
) return false;
1732 if (!TerminateJobObject(m_job
, (UINT
)-1))
1734 set_error(GetLastError());
1742 bool async_subprocess::kill(void)
1744 if (m_pid
== -1) return false;
1748 if (::kill(m_pid
, SIGINT
) == -1)
1760 int async_subprocess::write_stdin (std::string
& buffer
)
1762 if (m_child_in
== 0) return -1;
1763 // there doesn't seem to be a way of doing non-blocking writes under Windoze
1765 if (!WriteFile(m_child_in
, buffer
.c_str(), (DWORD
)buffer
.size(), &bytes
, 0))
1767 set_error(GetLastError());
1771 // now discard that part of the buffer that was written
1773 buffer
.erase(0, bytes
);
1779 int async_subprocess::write_stdin (std::string
& buffer
)
1781 if (m_child_in
== -1) return -1;
1782 // relies on the pipe being non-blocking
1783 // This does block under Windoze
1784 int bytes
= write(m_child_in
, buffer
.c_str(), buffer
.size());
1785 if (bytes
== -1 && errno
== EAGAIN
)
1792 // error on write - close the pipe and give up
1798 // now discard that part of the buffer that was written
1800 buffer
.erase(0, bytes
);
1808 int async_subprocess::read_stdout (std::string
& buffer
)
1810 if (m_child_out
== 0) return -1;
1811 // peek at the buffer to see how much data there is in the first place
1812 DWORD buffer_size
= 0;
1813 if (!PeekNamedPipe(m_child_out
, 0, 0, 0, &buffer_size
, 0))
1815 if (GetLastError() != ERROR_BROKEN_PIPE
)
1816 set_error(GetLastError());
1820 if (buffer_size
== 0) return 0;
1822 char* tmp
= new char[buffer_size
];
1823 if (!ReadFile(m_child_out
, tmp
, buffer_size
, &bytes
, 0))
1825 set_error(GetLastError());
1837 buffer
.append(tmp
, bytes
);
1844 int async_subprocess::read_stdout (std::string
& buffer
)
1846 if (m_child_out
== -1) return -1;
1847 // rely on the pipe being non-blocking
1848 int buffer_size
= 256;
1849 char* tmp
= new char[buffer_size
];
1850 int bytes
= read(m_child_out
, tmp
, buffer_size
);
1851 if (bytes
== -1 && errno
== EAGAIN
)
1873 buffer
.append(tmp
, bytes
);
1882 int async_subprocess::read_stderr (std::string
& buffer
)
1884 if (m_child_err
== 0) return -1;
1885 // peek at the buffer to see how much data there is in the first place
1886 DWORD buffer_size
= 0;
1887 if (!PeekNamedPipe(m_child_err
, 0, 0, 0, &buffer_size
, 0))
1889 if (GetLastError() != ERROR_BROKEN_PIPE
)
1890 set_error(GetLastError());
1894 if (buffer_size
== 0) return 0;
1896 char* tmp
= new char[buffer_size
];
1897 if (!ReadFile(m_child_err
, tmp
, buffer_size
, &bytes
, 0))
1899 set_error(GetLastError());
1911 buffer
.append(tmp
, bytes
);
1918 int async_subprocess::read_stderr (std::string
& buffer
)
1920 if (m_child_err
== -1) return -1;
1921 // rely on the pipe being non-blocking
1922 int buffer_size
= 256;
1923 char* tmp
= new char[buffer_size
];
1924 int bytes
= read(m_child_err
, tmp
, buffer_size
);
1925 if (bytes
== -1 && errno
== EAGAIN
)
1947 buffer
.append(tmp
, bytes
);
1956 void async_subprocess::close_stdin (void)
1960 CloseHandle(m_child_in
);
1967 void async_subprocess::close_stdin (void)
1969 if (m_child_in
!= -1)
1971 ::close(m_child_in
);
1980 void async_subprocess::close_stdout (void)
1984 CloseHandle(m_child_out
);
1991 void async_subprocess::close_stdout (void)
1993 if (m_child_out
!= -1)
1995 ::close(m_child_out
);
2004 void async_subprocess::close_stderr (void)
2008 CloseHandle(m_child_err
);
2015 void async_subprocess::close_stderr (void)
2017 if (m_child_err
!= -1)
2019 ::close(m_child_err
);
2026 bool async_subprocess::error(void) const
2031 int async_subprocess::error_number(void) const
2038 std::string
async_subprocess::error_text(void) const
2040 if (m_err
== 0) return std::string();
2042 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_IGNORE_INSERTS
,
2045 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
2048 std::string result
= message
;
2050 // the error message is for some perverse reason newline terminated - remove this
2051 if (result
[result
.size()-1] == '\n')
2052 result
.erase(result
.end()-1);
2053 if (result
[result
.size()-1] == '\r')
2054 result
.erase(result
.end()-1);
2060 std::string
async_subprocess::error_text(void) const
2062 if (m_err
== 0) return std::string();
2063 char* text
= strerror(m_err
);
2064 if (text
) return std::string(text
);
2065 return "error number " + dformat("%d",m_err
);
2070 int async_subprocess::exit_status(void) const
2075 ////////////////////////////////////////////////////////////////////////////////
2077 } // end namespace stlplus