28#define _RWSTD_TEST_SRC
58# if defined (_RWSTD_OS_AIX) || defined (_RWSTD_OS_OSF)
61# elif defined (_RWSTD_OS_LINUX)
109_rw_map_errno (DWORD err)
111 if (ERROR_WRITE_PROTECT <= err && ERROR_SHARING_BUFFER_EXCEEDED >= err)
114 if ( ERROR_INVALID_STARTING_CODESEG <= err
115 && ERROR_INFLOOP_IN_RELOC_CHAIN >= err) {
122 case ERROR_FILE_NOT_FOUND:
123 case ERROR_PATH_NOT_FOUND:
124 case ERROR_INVALID_DRIVE:
125 case ERROR_NO_MORE_FILES:
126 case ERROR_BAD_NETPATH:
127 case ERROR_BAD_NET_NAME:
128 case ERROR_INVALID_NAME:
129 case ERROR_BAD_PATHNAME:
130 case ERROR_FILENAME_EXCED_RANGE:
134 case ERROR_TOO_MANY_OPEN_FILES:
137 case ERROR_ACCESS_DENIED:
138 case ERROR_CURRENT_DIRECTORY:
139 case ERROR_NETWORK_ACCESS_DENIED:
140 case ERROR_CANNOT_MAKE:
142 case ERROR_DRIVE_LOCKED:
143 case ERROR_SEEK_ON_DEVICE:
144 case ERROR_NOT_LOCKED:
145 case ERROR_LOCK_FAILED:
148 case ERROR_INVALID_HANDLE:
149 case ERROR_INVALID_TARGET_HANDLE:
150 case ERROR_DIRECT_ACCESS_HANDLE:
153 case ERROR_ARENA_TRASHED:
154 case ERROR_NOT_ENOUGH_MEMORY:
155 case ERROR_INVALID_BLOCK:
156 case ERROR_NOT_ENOUGH_QUOTA:
159 case ERROR_BAD_ENVIRONMENT:
162 case ERROR_BAD_FORMAT:
165 case ERROR_NOT_SAME_DEVICE:
168 case ERROR_FILE_EXISTS:
171 case ERROR_NO_PROC_SLOTS:
172 case ERROR_MAX_THRDS_REACHED:
173 case ERROR_NESTING_NOT_ALLOWED:
176 case ERROR_BROKEN_PIPE:
179 case ERROR_DISK_FULL:
182 case ERROR_WAIT_NO_CHILDREN:
183 case ERROR_CHILD_NOT_COMPLETE:
186 case ERROR_DIR_NOT_EMPTY:
189 case ERROR_ALREADY_EXISTS:
198# include <sys/types.h>
199# include <sys/wait.h>
212_rw_split_cmd (
char* cmd,
char** argv,
size_t size)
218 for (
char* end = cmd + strlen (cmd); cmd !=
end; ) {
220 while (isspace (*cmd))
226 if (argv && ret <
size)
231 if (
'\'' == *cmd ||
'\"' == *cmd) {
232 char*
const cmd1 = cmd + 1;
234 char*
const pos = strchr (cmd1, *cmd);
238 memmove (cmd, cmd1,
pos - cmd1);
241 memmove (cmd,
pos + 1, end -
pos);
251 while (*cmd && !isspace (*cmd))
267_rw_vsystem (
const char *cmd, va_list va)
275 rw_note (0,
"file:" __FILE__, __LINE__,
"executing \"%s\"",
buf);
290 "system (\"%s\") failed: errno = %{#m} (%{m})",
293 else if (WIFSIGNALED (ret)) {
295 const int signo = WTERMSIG (ret);
298 "the command \"%s\" exited with signal %d (%{K})",
303 const int status = WEXITSTATUS (ret);
306 "the command \"%s\" exited with status %d",
313 "the command \"%s\" failed with code %d",
333 const int ret = _rw_vsystem (cmd, va);
342_rw_vprocess_create (
const char* cmd, va_list va)
354 STARTUPINFO si = {
sizeof (si) };
355 PROCESS_INFORMATION pi;
357 if (CreateProcess (0,
buf, 0, 0, FALSE,
358 CREATE_NEW_PROCESS_GROUP, 0, 0, &si, &pi)) {
360 CloseHandle (pi.hThread);
364 const DWORD err = GetLastError ();
367 "CreateProcess () failed: GetLastError() = %zu",
370 errno = _rw_map_errno (err);
375 const size_t MAX_PARAMS = 63;
376 char* argv [MAX_PARAMS + 1] = { 0 };
378 size_t argc = _rw_split_cmd (
buf, argv, MAX_PARAMS);
380 if (0 < argc && MAX_PARAMS >= argc)
400 const rw_pid_t ret = _rw_vprocess_create (cmd, va);
417 if (0 == access (
path, X_OK)) {
421 if (0 == child_pid) {
427 "errno = %{#m} (%{m})\n",
428 __FILE__, __LINE__,
path, argv);
432 else if (-1 == child_pid)
434 "fork () failed: errno = %{#m} (%{m})");
440 "access (%#s, X_OK) failed: errno = %{#m} (%{m})",
459 if (-1 == pid || -2 == pid) {
464 const HANDLE handle = HANDLE (pid);
466 const DWORD milliseconds =
467 0 > timeout ? INFINITE : DWORD (timeout * 1000);
469 const DWORD
res = WaitForSingleObject (handle, milliseconds);
471 DWORD err = ERROR_SUCCESS;
473 if (WAIT_OBJECT_0 ==
res) {
476 if (GetExitCodeProcess (handle, &dwExitCode)) {
478 CloseHandle (handle);
482 "the process (pid=%{P}) exited with return code %d",
483 pid,
int (dwExitCode));
486 *
result = int (dwExitCode);
491 err = GetLastError ();
493 "GetExitCodeProcess (%{P}, %#p) failed: GetLastError() = %zu",
494 pid, &dwExitCode,
size_t (err));
496 else if (WAIT_FAILED ==
res) {
497 err = GetLastError ();
499 "WaitForSingleObject (%{P}, %{?}INFINITE%{:}%zu%{;}) failed: "
500 "GetLastError() = %zu",
501 pid, INFINITE == milliseconds,
502 size_t (milliseconds),
size_t (err));
510 if (ERROR_INVALID_HANDLE == err)
513 errno = _rw_map_errno (err);
522static int alarm_timeout;
524static void handle_alarm_signal (
int) {
535#ifdef _RWSTD_EDG_ECCP
536# define _RWSTD_NO_SIGACTION
539#ifndef _RWSTD_NO_SIGACTION
540 struct sigaction prev_alarm_action;
544 int prev_alarm_timeout = 0;
549#ifndef _RWSTD_NO_SIGACTION
550 struct sigaction alarm_action;
551 memset (&alarm_action, 0,
sizeof alarm_action);
554 memcpy (&alarm_action.sa_handler, &handler_fun,
555 sizeof alarm_action.sa_handler);
557 sigaction (
SIGALRM, &alarm_action, &prev_alarm_action);
559 prev_alarm_handler = signal (
SIGALRM, handle_alarm_signal);
561 prev_alarm_timeout = alarm (timeout);
575 ret = waitpid (pid_t (pid), &status, 0);
579 if (
EINTR == errno && alarm_timeout) {
584 else if (
EINTR == errno) {
586 rw_warn (0, __FILE__, __LINE__,
587 "waitpid (%{P}, %#p, 0) interrupted: "
588 "errno = %{#m} (%{m})",
596 "waitpid (%{P}, %#p, 0) failed: "
597 "errno = %{#m} (%{m})",
602 else if (ret == pid) {
604 if (WIFSIGNALED (status)) {
606 const int signo = WTERMSIG (status);
609 "the process (pid=%{P}) exited with signal %d (%{K})",
614 else if (WIFEXITED (status)) {
616 const int retcode = WEXITSTATUS (status);
620 "the process (pid=%{P}) exited with return code %d",
637 if (prev_alarm_timeout) {
640 if (delta < prev_alarm_timeout)
641 prev_alarm_timeout -= delta;
643 prev_alarm_timeout = 1;
646 alarm (prev_alarm_timeout);
648#ifndef _RWSTD_NO_SIGACTION
649 sigaction (
SIGALRM, &prev_alarm_action, 0);
651 signal (
SIGALRM, prev_alarm_handler);
666 const int timeout = 1;
671 if (!TerminateProcess (HANDLE (pid), DWORD (signo))) {
673 const DWORD err = GetLastError ();
675 "TerminateProcess (%{P}, %i) failed: GetLastError() = %zu",
676 pid, signo,
size_t (err));
678 if (ERROR_INVALID_HANDLE == err)
680 else if (ERROR_ACCESS_DENIED == err)
683 errno = _rw_map_errno (err);
695 "rw_waitpid (%{P}, 0, %i) failed: errno = %{#m} (%{m})",
702 static const int signals_ [] = {
706 const int*
const signals = (-1 == signo) ? signals_ : &signo;
708 const unsigned sigcount =
709 (-1 == signo) ?
unsigned (
sizeof (signals_) /
sizeof (*signals_)) : 1;
713 for (
unsigned i = 0;
i < sigcount; ++
i) {
716 ret =
kill (pid_t (pid), signals [
i]);
720 "kill (%{P}, %{K}) failed: errno = %{#m} (%{m})",
733 "rw_waitpid (%{P}, 0, %i) failed: errno = %{#m} (%{m})",
IMPORT_C SInt32 system(const Char *)
#define va_start(va, name)
int kill(pid_t pid, int sig)
_TEST_EXPORT int rw_system(const char *cmd,...)
_TEST_EXPORT rw_pid_t rw_waitpid(rw_pid_t pid, int *presult, int timeout)
_TEST_EXPORT int rw_process_kill(rw_pid_t pid, int signo)
void(* signal_handler_t)(int)
_TEST_EXPORT rw_pid_t rw_process_create(const char *cmd,...)
_TEST_EXPORT int rw_vasnprintf(char **, size_t *, const char *, va_list)
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_warn(int, const char *, int, const char *,...)
_TEST_EXPORT rw_file *const rw_stderr
_TEST_EXPORT int rw_fprintf(rw_file *, const char *,...)