Wed Oct 9 01:18:55 2019 UTC ()
the cast police is looking for me.


(christos)
diff -r1.1.1.2 -r1.2 src/external/bsd/atf/dist/atf-c++/build.cpp
diff -r1.11 -r1.12 src/external/bsd/atf/dist/atf-sh/atf-check.cpp
diff -r1.5 -r1.6 src/external/bsd/atf/dist/tools/process.cpp

cvs diff -r1.1.1.2 -r1.2 src/external/bsd/atf/dist/atf-c++/build.cpp (switch to unified diff)

--- src/external/bsd/atf/dist/atf-c++/build.cpp 2010/10/20 09:14:20 1.1.1.2
+++ src/external/bsd/atf/dist/atf-c++/build.cpp 2019/10/09 01:18:55 1.2
@@ -1,119 +1,119 @@ @@ -1,119 +1,119 @@
1// 1//
2// Automated Testing Framework (atf) 2// Automated Testing Framework (atf)
3// 3//
4// Copyright (c) 2009 The NetBSD Foundation, Inc. 4// Copyright (c) 2009 The NetBSD Foundation, Inc.
5// All rights reserved. 5// All rights reserved.
6// 6//
7// Redistribution and use in source and binary forms, with or without 7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions 8// modification, are permitted provided that the following conditions
9// are met: 9// are met:
10// 1. Redistributions of source code must retain the above copyright 10// 1. Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer. 11// notice, this list of conditions and the following disclaimer.
12// 2. Redistributions in binary form must reproduce the above copyright 12// 2. Redistributions in binary form must reproduce the above copyright
13// notice, this list of conditions and the following disclaimer in the 13// notice, this list of conditions and the following disclaimer in the
14// documentation and/or other materials provided with the distribution. 14// documentation and/or other materials provided with the distribution.
15// 15//
16// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 16// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 20// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28// 28//
29 29
30extern "C" { 30extern "C" {
31#include "atf-c/build.h" 31#include "atf-c/build.h"
32#include "atf-c/error.h" 32#include "atf-c/error.h"
33#include "atf-c/utils.h" 33#include "atf-c/utils.h"
34} 34}
35 35
36#include "build.hpp" 36#include "build.hpp"
37 37
38#include "detail/exceptions.hpp" 38#include "detail/exceptions.hpp"
39#include "detail/process.hpp" 39#include "detail/process.hpp"
40 40
41namespace impl = atf::build; 41namespace impl = atf::build;
42#define IMPL_NAME "atf::build" 42#define IMPL_NAME "atf::build"
43 43
44// ------------------------------------------------------------------------ 44// ------------------------------------------------------------------------
45// Auxiliary functions. 45// Auxiliary functions.
46// ------------------------------------------------------------------------ 46// ------------------------------------------------------------------------
47 47
48inline 48inline
49atf::process::argv_array 49atf::process::argv_array
50cargv_to_argv(const atf_list_t* l) 50cargv_to_argv(const atf_list_t* l)
51{ 51{
52 std::vector< const char* > aux; 52 std::vector< const char* > aux;
53 53
54 atf_list_citer_t iter; 54 atf_list_citer_t iter;
55 atf_list_for_each_c(iter, l) 55 atf_list_for_each_c(iter, l)
56 aux.push_back(static_cast< const char* >(atf_list_citer_data(iter))); 56 aux.push_back(static_cast< const char* >(atf_list_citer_data(iter)));
57 57
58 return atf::process::argv_array(aux); 58 return atf::process::argv_array(aux);
59} 59}
60 60
61inline 61inline
62atf::process::argv_array 62atf::process::argv_array
63cargv_to_argv_and_free(char** l) 63cargv_to_argv_and_free(char** l)
64{ 64{
65 try { 65 try {
66 atf::process::argv_array argv((const char* const*)l); 66 atf::process::argv_array argv(const_cast<const char* const*>(l));
67 atf_utils_free_charpp(l); 67 atf_utils_free_charpp(l);
68 return argv; 68 return argv;
69 } catch (...) { 69 } catch (...) {
70 atf_utils_free_charpp(l); 70 atf_utils_free_charpp(l);
71 throw; 71 throw;
72 } 72 }
73} 73}
74 74
75// ------------------------------------------------------------------------ 75// ------------------------------------------------------------------------
76// Free functions. 76// Free functions.
77// ------------------------------------------------------------------------ 77// ------------------------------------------------------------------------
78 78
79atf::process::argv_array 79atf::process::argv_array
80impl::c_o(const std::string& sfile, const std::string& ofile, 80impl::c_o(const std::string& sfile, const std::string& ofile,
81 const atf::process::argv_array& optargs) 81 const atf::process::argv_array& optargs)
82{ 82{
83 char** l; 83 char** l;
84 84
85 atf_error_t err = atf_build_c_o(sfile.c_str(), ofile.c_str(), 85 atf_error_t err = atf_build_c_o(sfile.c_str(), ofile.c_str(),
86 optargs.exec_argv(), &l); 86 optargs.exec_argv(), &l);
87 if (atf_is_error(err)) 87 if (atf_is_error(err))
88 throw_atf_error(err); 88 throw_atf_error(err);
89 89
90 return cargv_to_argv_and_free(l); 90 return cargv_to_argv_and_free(l);
91} 91}
92 92
93atf::process::argv_array 93atf::process::argv_array
94impl::cpp(const std::string& sfile, const std::string& ofile, 94impl::cpp(const std::string& sfile, const std::string& ofile,
95 const atf::process::argv_array& optargs) 95 const atf::process::argv_array& optargs)
96{ 96{
97 char** l; 97 char** l;
98 98
99 atf_error_t err = atf_build_cpp(sfile.c_str(), ofile.c_str(), 99 atf_error_t err = atf_build_cpp(sfile.c_str(), ofile.c_str(),
100 optargs.exec_argv(), &l); 100 optargs.exec_argv(), &l);
101 if (atf_is_error(err)) 101 if (atf_is_error(err))
102 throw_atf_error(err); 102 throw_atf_error(err);
103 103
104 return cargv_to_argv_and_free(l); 104 return cargv_to_argv_and_free(l);
105} 105}
106 106
107atf::process::argv_array 107atf::process::argv_array
108impl::cxx_o(const std::string& sfile, const std::string& ofile, 108impl::cxx_o(const std::string& sfile, const std::string& ofile,
109 const atf::process::argv_array& optargs) 109 const atf::process::argv_array& optargs)
110{ 110{
111 char** l; 111 char** l;
112 112
113 atf_error_t err = atf_build_cxx_o(sfile.c_str(), ofile.c_str(), 113 atf_error_t err = atf_build_cxx_o(sfile.c_str(), ofile.c_str(),
114 optargs.exec_argv(), &l); 114 optargs.exec_argv(), &l);
115 if (atf_is_error(err)) 115 if (atf_is_error(err))
116 throw_atf_error(err); 116 throw_atf_error(err);
117 117
118 return cargv_to_argv_and_free(l); 118 return cargv_to_argv_and_free(l);
119} 119}

cvs diff -r1.11 -r1.12 src/external/bsd/atf/dist/atf-sh/atf-check.cpp (switch to unified diff)

--- src/external/bsd/atf/dist/atf-sh/atf-check.cpp 2019/10/04 09:19:18 1.11
+++ src/external/bsd/atf/dist/atf-sh/atf-check.cpp 2019/10/09 01:18:55 1.12
@@ -1,847 +1,847 @@ @@ -1,847 +1,847 @@
1// 1//
2// Automated Testing Framework (atf) 2// Automated Testing Framework (atf)
3// 3//
4// Copyright (c) 2008 The NetBSD Foundation, Inc. 4// Copyright (c) 2008 The NetBSD Foundation, Inc.
5// All rights reserved. 5// All rights reserved.
6// 6//
7// Redistribution and use in source and binary forms, with or without 7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions 8// modification, are permitted provided that the following conditions
9// are met: 9// are met:
10// 1. Redistributions of source code must retain the above copyright 10// 1. Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer. 11// notice, this list of conditions and the following disclaimer.
12// 2. Redistributions in binary form must reproduce the above copyright 12// 2. Redistributions in binary form must reproduce the above copyright
13// notice, this list of conditions and the following disclaimer in the 13// notice, this list of conditions and the following disclaimer in the
14// documentation and/or other materials provided with the distribution. 14// documentation and/or other materials provided with the distribution.
15// 15//
16// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 16// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 20// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28// 28//
29 29
30extern "C" { 30extern "C" {
31#include <sys/types.h> 31#include <sys/types.h>
32#include <sys/wait.h> 32#include <sys/wait.h>
33 33
34#include <limits.h> 34#include <limits.h>
35#include <signal.h> 35#include <signal.h>
36#include <unistd.h> 36#include <unistd.h>
37} 37}
38 38
39#include <cerrno> 39#include <cerrno>
40#include <cstdlib> 40#include <cstdlib>
41#include <cstring> 41#include <cstring>
42#include <fstream> 42#include <fstream>
43#include <ios> 43#include <ios>
44#include <iostream> 44#include <iostream>
45#include <iterator> 45#include <iterator>
46#include <list> 46#include <list>
47#include <memory> 47#include <memory>
48#include <utility> 48#include <utility>
49 49
50#include "atf-c++/check.hpp" 50#include "atf-c++/check.hpp"
51#include "atf-c++/config.hpp" 51#include "atf-c++/config.hpp"
52 52
53#include "atf-c++/detail/application.hpp" 53#include "atf-c++/detail/application.hpp"
54#include "atf-c++/detail/auto_array.hpp" 54#include "atf-c++/detail/auto_array.hpp"
55#include "atf-c++/detail/exceptions.hpp" 55#include "atf-c++/detail/exceptions.hpp"
56#include "atf-c++/detail/fs.hpp" 56#include "atf-c++/detail/fs.hpp"
57#include "atf-c++/detail/process.hpp" 57#include "atf-c++/detail/process.hpp"
58#include "atf-c++/detail/sanity.hpp" 58#include "atf-c++/detail/sanity.hpp"
59#include "atf-c++/detail/text.hpp" 59#include "atf-c++/detail/text.hpp"
60 60
61// ------------------------------------------------------------------------ 61// ------------------------------------------------------------------------
62// Auxiliary functions. 62// Auxiliary functions.
63// ------------------------------------------------------------------------ 63// ------------------------------------------------------------------------
64 64
65namespace { 65namespace {
66 66
67enum status_check_t { 67enum status_check_t {
68 sc_exit, 68 sc_exit,
69 sc_ignore, 69 sc_ignore,
70 sc_signal, 70 sc_signal,
71}; 71};
72 72
73struct status_check { 73struct status_check {
74 status_check_t type; 74 status_check_t type;
75 bool negated; 75 bool negated;
76 int value; 76 int value;
77 77
78 status_check(const status_check_t& p_type, const bool p_negated, 78 status_check(const status_check_t& p_type, const bool p_negated,
79 const int p_value) : 79 const int p_value) :
80 type(p_type), 80 type(p_type),
81 negated(p_negated), 81 negated(p_negated),
82 value(p_value) 82 value(p_value)
83 { 83 {
84 } 84 }
85}; 85};
86 86
87enum output_check_t { 87enum output_check_t {
88 oc_ignore, 88 oc_ignore,
89 oc_inline, 89 oc_inline,
90 oc_file, 90 oc_file,
91 oc_empty, 91 oc_empty,
92 oc_match, 92 oc_match,
93 oc_save 93 oc_save
94}; 94};
95 95
96struct output_check { 96struct output_check {
97 output_check_t type; 97 output_check_t type;
98 bool negated; 98 bool negated;
99 std::string value; 99 std::string value;
100 100
101 output_check(const output_check_t& p_type, const bool p_negated, 101 output_check(const output_check_t& p_type, const bool p_negated,
102 const std::string& p_value) : 102 const std::string& p_value) :
103 type(p_type), 103 type(p_type),
104 negated(p_negated), 104 negated(p_negated),
105 value(p_value) 105 value(p_value)
106 { 106 {
107 } 107 }
108}; 108};
109 109
110class temp_file : public std::ostream { 110class temp_file : public std::ostream {
111 std::auto_ptr< atf::fs::path > m_path; 111 std::auto_ptr< atf::fs::path > m_path;
112 int m_fd; 112 int m_fd;
113 113
114public: 114public:
115 temp_file(const atf::fs::path& p) : 115 temp_file(const atf::fs::path& p) :
116 std::ostream(NULL), 116 std::ostream(NULL),
117 m_fd(-1) 117 m_fd(-1)
118 { 118 {
119 atf::auto_array< char > buf(new char[p.str().length() + 1]); 119 atf::auto_array< char > buf(new char[p.str().length() + 1]);
120 std::strcpy(buf.get(), p.c_str()); 120 std::strcpy(buf.get(), p.c_str());
121 121
122 m_fd = ::mkstemp(buf.get()); 122 m_fd = ::mkstemp(buf.get());
123 if (m_fd == -1) 123 if (m_fd == -1)
124 throw atf::system_error("atf_check::temp_file::temp_file(" + 124 throw atf::system_error("atf_check::temp_file::temp_file(" +
125 p.str() + ")", "mkstemp(3) failed", 125 p.str() + ")", "mkstemp(3) failed",
126 errno); 126 errno);
127 127
128 m_path.reset(new atf::fs::path(buf.get())); 128 m_path.reset(new atf::fs::path(buf.get()));
129 } 129 }
130 130
131 ~temp_file(void) 131 ~temp_file(void)
132 { 132 {
133 close(); 133 close();
134 try { 134 try {
135 remove(*m_path); 135 remove(*m_path);
136 } catch (const atf::system_error&) { 136 } catch (const atf::system_error&) {
137 // Ignore deletion errors. 137 // Ignore deletion errors.
138 } 138 }
139 } 139 }
140 140
141 const atf::fs::path& 141 const atf::fs::path&
142 get_path(void) const 142 get_path(void) const
143 { 143 {
144 return *m_path; 144 return *m_path;
145 } 145 }
146 146
147 void 147 void
148 write(const std::string& text) 148 write(const std::string& text)
149 { 149 {
150 if (::write(m_fd, text.c_str(), text.size()) == -1) 150 if (::write(m_fd, text.c_str(), text.size()) == -1)
151 throw atf::system_error("atf_check", "write(2) failed", errno); 151 throw atf::system_error("atf_check", "write(2) failed", errno);
152 } 152 }
153 153
154 void 154 void
155 close(void) 155 close(void)
156 { 156 {
157 if (m_fd != -1) { 157 if (m_fd != -1) {
158 flush(); 158 flush();
159 ::close(m_fd); 159 ::close(m_fd);
160 m_fd = -1; 160 m_fd = -1;
161 } 161 }
162 } 162 }
163}; 163};
164 164
165} // anonymous namespace 165} // anonymous namespace
166 166
167static int 167static int
168parse_exit_code(const std::string& str) 168parse_exit_code(const std::string& str)
169{ 169{
170 try { 170 try {
171 const int value = atf::text::to_type< int >(str); 171 const int value = atf::text::to_type< int >(str);
172 if (value < 0 || value > 255) 172 if (value < 0 || value > 255)
173 throw std::runtime_error("Unused reason"); 173 throw std::runtime_error("Unused reason");
174 return value; 174 return value;
175 } catch (const std::runtime_error&) { 175 } catch (const std::runtime_error&) {
176 throw atf::application::usage_error("Invalid exit code for -s option; " 176 throw atf::application::usage_error("Invalid exit code for -s option; "
177 "must be an integer in range 0-255"); 177 "must be an integer in range 0-255");
178 } 178 }
179} 179}
180 180
181static struct name_number { 181static struct name_number {
182 const char *name; 182 const char *name;
183 int signo; 183 int signo;
184} signal_names_to_numbers[] = { 184} signal_names_to_numbers[] = {
185 { "hup", SIGHUP }, 185 { "hup", SIGHUP },
186 { "int", SIGINT }, 186 { "int", SIGINT },
187 { "quit", SIGQUIT }, 187 { "quit", SIGQUIT },
188 { "trap", SIGTRAP }, 188 { "trap", SIGTRAP },
189 { "abrt", SIGABRT }, 189 { "abrt", SIGABRT },
190 { "kill", SIGKILL }, 190 { "kill", SIGKILL },
191 { "segv", SIGSEGV }, 191 { "segv", SIGSEGV },
192 { "pipe", SIGPIPE }, 192 { "pipe", SIGPIPE },
193 { "alrm", SIGALRM }, 193 { "alrm", SIGALRM },
194 { "term", SIGTERM }, 194 { "term", SIGTERM },
195 { "usr1", SIGUSR1 }, 195 { "usr1", SIGUSR1 },
196 { "usr2", SIGUSR2 }, 196 { "usr2", SIGUSR2 },
197 { NULL, INT_MIN }, 197 { NULL, INT_MIN },
198}; 198};
199 199
200static int 200static int
201signal_name_to_number(const std::string& str) 201signal_name_to_number(const std::string& str)
202{ 202{
203 struct name_number* iter = signal_names_to_numbers; 203 struct name_number* iter = signal_names_to_numbers;
204 int signo = INT_MIN; 204 int signo = INT_MIN;
205 while (signo == INT_MIN && iter->name != NULL) { 205 while (signo == INT_MIN && iter->name != NULL) {
206 if (str == iter->name || str == std::string("sig") + iter->name) 206 if (str == iter->name || str == std::string("sig") + iter->name)
207 signo = iter->signo; 207 signo = iter->signo;
208 else 208 else
209 iter++; 209 iter++;
210 } 210 }
211 return signo; 211 return signo;
212} 212}
213 213
214static int 214static int
215parse_signal(const std::string& str) 215parse_signal(const std::string& str)
216{ 216{
217 const int signo = signal_name_to_number(str); 217 const int signo = signal_name_to_number(str);
218 if (signo == INT_MIN) { 218 if (signo == INT_MIN) {
219 try { 219 try {
220 return atf::text::to_type< int >(str); 220 return atf::text::to_type< int >(str);
221 } catch (std::runtime_error &e) { 221 } catch (std::runtime_error &e) {
222 throw atf::application::usage_error("Invalid signal name or number " 222 throw atf::application::usage_error("Invalid signal name or number "
223 "in -s option"); 223 "in -s option");
224 } 224 }
225 } 225 }
226 INV(signo != INT_MIN); 226 INV(signo != INT_MIN);
227 return signo; 227 return signo;
228} 228}
229 229
230static status_check 230static status_check
231parse_status_check_arg(const std::string& arg) 231parse_status_check_arg(const std::string& arg)
232{ 232{
233 const std::string::size_type delimiter = arg.find(':'); 233 const std::string::size_type delimiter = arg.find(':');
234 bool negated = (arg.compare(0, 4, "not-") == 0); 234 bool negated = (arg.compare(0, 4, "not-") == 0);
235 const std::string action_str = arg.substr(0, delimiter); 235 const std::string action_str = arg.substr(0, delimiter);
236 const std::string action = negated ? action_str.substr(4) : action_str; 236 const std::string action = negated ? action_str.substr(4) : action_str;
237 const std::string value_str = ( 237 const std::string value_str = (
238 delimiter == std::string::npos ? "" : arg.substr(delimiter + 1)); 238 delimiter == std::string::npos ? "" : arg.substr(delimiter + 1));
239 int value; 239 int value;
240 240
241 status_check_t type; 241 status_check_t type;
242 if (action == "eq") { 242 if (action == "eq") {
243 // Deprecated; use exit instead. TODO: Remove after 0.10. 243 // Deprecated; use exit instead. TODO: Remove after 0.10.
244 type = sc_exit; 244 type = sc_exit;
245 if (negated) 245 if (negated)
246 throw atf::application::usage_error("Cannot negate eq checker"); 246 throw atf::application::usage_error("Cannot negate eq checker");
247 negated = false; 247 negated = false;
248 value = parse_exit_code(value_str); 248 value = parse_exit_code(value_str);
249 } else if (action == "exit") { 249 } else if (action == "exit") {
250 type = sc_exit; 250 type = sc_exit;
251 if (value_str.empty()) 251 if (value_str.empty())
252 value = INT_MIN; 252 value = INT_MIN;
253 else 253 else
254 value = parse_exit_code(value_str); 254 value = parse_exit_code(value_str);
255 } else if (action == "ignore") { 255 } else if (action == "ignore") {
256 if (negated) 256 if (negated)
257 throw atf::application::usage_error("Cannot negate ignore checker"); 257 throw atf::application::usage_error("Cannot negate ignore checker");
258 type = sc_ignore; 258 type = sc_ignore;
259 value = INT_MIN; 259 value = INT_MIN;
260 } else if (action == "ne") { 260 } else if (action == "ne") {
261 // Deprecated; use not-exit instead. TODO: Remove after 0.10. 261 // Deprecated; use not-exit instead. TODO: Remove after 0.10.
262 type = sc_exit; 262 type = sc_exit;
263 if (negated) 263 if (negated)
264 throw atf::application::usage_error("Cannot negate ne checker"); 264 throw atf::application::usage_error("Cannot negate ne checker");
265 negated = true; 265 negated = true;
266 value = parse_exit_code(value_str); 266 value = parse_exit_code(value_str);
267 } else if (action == "signal") { 267 } else if (action == "signal") {
268 type = sc_signal; 268 type = sc_signal;
269 if (value_str.empty()) 269 if (value_str.empty())
270 value = INT_MIN; 270 value = INT_MIN;
271 else 271 else
272 value = parse_signal(value_str); 272 value = parse_signal(value_str);
273 } else 273 } else
274 throw atf::application::usage_error("Invalid status checker"); 274 throw atf::application::usage_error("Invalid status checker");
275 275
276 return status_check(type, negated, value); 276 return status_check(type, negated, value);
277} 277}
278 278
279static 279static
280output_check 280output_check
281parse_output_check_arg(const std::string& arg) 281parse_output_check_arg(const std::string& arg)
282{ 282{
283 const std::string::size_type delimiter = arg.find(':'); 283 const std::string::size_type delimiter = arg.find(':');
284 const bool negated = (arg.compare(0, 4, "not-") == 0); 284 const bool negated = (arg.compare(0, 4, "not-") == 0);
285 const std::string action_str = arg.substr(0, delimiter); 285 const std::string action_str = arg.substr(0, delimiter);
286 const std::string action = negated ? action_str.substr(4) : action_str; 286 const std::string action = negated ? action_str.substr(4) : action_str;
287 287
288 output_check_t type; 288 output_check_t type;
289 if (action == "empty") 289 if (action == "empty")
290 type = oc_empty; 290 type = oc_empty;
291 else if (action == "file") 291 else if (action == "file")
292 type = oc_file; 292 type = oc_file;
293 else if (action == "ignore") { 293 else if (action == "ignore") {
294 if (negated) 294 if (negated)
295 throw atf::application::usage_error("Cannot negate ignore checker"); 295 throw atf::application::usage_error("Cannot negate ignore checker");
296 type = oc_ignore; 296 type = oc_ignore;
297 } else if (action == "inline") 297 } else if (action == "inline")
298 type = oc_inline; 298 type = oc_inline;
299 else if (action == "match") 299 else if (action == "match")
300 type = oc_match; 300 type = oc_match;
301 else if (action == "save") { 301 else if (action == "save") {
302 if (negated) 302 if (negated)
303 throw atf::application::usage_error("Cannot negate save checker"); 303 throw atf::application::usage_error("Cannot negate save checker");
304 type = oc_save; 304 type = oc_save;
305 } else 305 } else
306 throw atf::application::usage_error("Invalid output checker"); 306 throw atf::application::usage_error("Invalid output checker");
307 307
308 return output_check(type, negated, arg.substr(delimiter + 1)); 308 return output_check(type, negated, arg.substr(delimiter + 1));
309} 309}
310 310
311static 311static
312std::string 312std::string
313flatten_argv(char* const* argv) 313flatten_argv(char* const* argv)
314{ 314{
315 std::string cmdline; 315 std::string cmdline;
316 316
317 char* const* arg = &argv[0]; 317 char* const* arg = &argv[0];
318 while (*arg != NULL) { 318 while (*arg != NULL) {
319 if (arg != &argv[0]) 319 if (arg != &argv[0])
320 cmdline += ' '; 320 cmdline += ' ';
321 321
322 cmdline += *arg; 322 cmdline += *arg;
323 323
324 arg++; 324 arg++;
325 } 325 }
326 326
327 return cmdline; 327 return cmdline;
328} 328}
329 329
330static 330static
331std::auto_ptr< atf::check::check_result > 331std::auto_ptr< atf::check::check_result >
332execute(const char* const* argv) 332execute(const char* const* argv)
333{ 333{
334 // TODO: This should go to stderr... but fixing it now may be hard as test 334 // TODO: This should go to stderr... but fixing it now may be hard as test
335 // cases out there might be relying on stderr being silent. 335 // cases out there might be relying on stderr being silent.
336 std::cout << "Executing command [ "; 336 std::cout << "Executing command [ ";
337 for (int i = 0; argv[i] != NULL; ++i) 337 for (int i = 0; argv[i] != NULL; ++i)
338 std::cout << argv[i] << " "; 338 std::cout << argv[i] << " ";
339 std::cout << "]\n"; 339 std::cout << "]\n";
340 std::cout.flush(); 340 std::cout.flush();
341 341
342 atf::process::argv_array argva(argv); 342 atf::process::argv_array argva(argv);
343 return atf::check::exec(argva); 343 return atf::check::exec(argva);
344} 344}
345 345
346static 346static
347std::auto_ptr< atf::check::check_result > 347std::auto_ptr< atf::check::check_result >
348execute_with_shell(char* const* argv) 348execute_with_shell(char* const* argv)
349{ 349{
350 const std::string cmd = flatten_argv(argv); 350 const std::string cmd = flatten_argv(argv);
351 351
352 const char* sh_argv[4]; 352 const char* sh_argv[4];
353 sh_argv[0] = atf::config::get("atf_shell").c_str(); 353 sh_argv[0] = atf::config::get("atf_shell").c_str();
354 sh_argv[1] = "-c"; 354 sh_argv[1] = "-c";
355 sh_argv[2] = cmd.c_str(); 355 sh_argv[2] = cmd.c_str();
356 sh_argv[3] = NULL; 356 sh_argv[3] = NULL;
357 return execute(sh_argv); 357 return execute(sh_argv);
358} 358}
359 359
360static 360static
361void 361void
362open_error(const atf::fs::path& path) 362open_error(const atf::fs::path& path)
363{ 363{
364 throw std::runtime_error("Failed to open " + path.str() + " " 364 throw std::runtime_error("Failed to open " + path.str() + " "
365 + ::strerror(errno)); 365 + ::strerror(errno));
366} 366}
367  367
368 368
369static 369static
370void 370void
371cat_file(const atf::fs::path& path) 371cat_file(const atf::fs::path& path)
372{ 372{
373 std::ifstream stream(path.c_str()); 373 std::ifstream stream(path.c_str());
374 if (!stream) 374 if (!stream)
375 open_error(path); 375 open_error(path);
376 376
377 stream >> std::noskipws; 377 stream >> std::noskipws;
378 std::istream_iterator< char > begin(stream), end; 378 std::istream_iterator< char > begin(stream), end;
379 std::ostream_iterator< char > out(std::cerr); 379 std::ostream_iterator< char > out(std::cerr);
380 std::copy(begin, end, out); 380 std::copy(begin, end, out);
381 381
382 stream.close(); 382 stream.close();
383} 383}
384 384
385static 385static
386bool 386bool
387grep_file(const atf::fs::path& path, const std::string& regexp) 387grep_file(const atf::fs::path& path, const std::string& regexp)
388{ 388{
389 std::ifstream stream(path.c_str()); 389 std::ifstream stream(path.c_str());
390 if (!stream) 390 if (!stream)
391 open_error(path); 391 open_error(path);
392 392
393 bool found = false; 393 bool found = false;
394 394
395 std::string line; 395 std::string line;
396 while (!found && !std::getline(stream, line).fail()) { 396 while (!found && !std::getline(stream, line).fail()) {
397 if (atf::text::match(line, regexp)) 397 if (atf::text::match(line, regexp))
398 found = true; 398 found = true;
399 } 399 }
400 400
401 stream.close(); 401 stream.close();
402 402
403 return found; 403 return found;
404} 404}
405 405
406static 406static
407bool 407bool
408file_empty(const atf::fs::path& p) 408file_empty(const atf::fs::path& p)
409{ 409{
410 atf::fs::file_info f(p); 410 atf::fs::file_info f(p);
411 411
412 return (f.get_size() == 0); 412 return (f.get_size() == 0);
413} 413}
414 414
415static bool 415static bool
416compare_files(const atf::fs::path& p1, const atf::fs::path& p2) 416compare_files(const atf::fs::path& p1, const atf::fs::path& p2)
417{ 417{
418 bool equal = false; 418 bool equal = false;
419 419
420 std::ifstream f1(p1.c_str()); 420 std::ifstream f1(p1.c_str());
421 if (!f1) 421 if (!f1)
422 open_error(p1); 422 open_error(p1);
423 423
424 std::ifstream f2(p2.c_str()); 424 std::ifstream f2(p2.c_str());
425 if (!f2) 425 if (!f2)
426 open_error(p2); 426 open_error(p2);
427 427
428 for (;;) { 428 for (;;) {
429 char buf1[512], buf2[512]; 429 char buf1[512], buf2[512];
430 430
431 f1.read(buf1, sizeof(buf1)); 431 f1.read(buf1, sizeof(buf1));
432 if (f1.bad()) 432 if (f1.bad())
433 throw std::runtime_error("Failed to read from " + p1.str()); 433 throw std::runtime_error("Failed to read from " + p1.str());
434 434
435 f2.read(buf2, sizeof(buf2)); 435 f2.read(buf2, sizeof(buf2));
436 if (f2.bad()) 436 if (f2.bad())
437 throw std::runtime_error("Failed to read from " + p1.str()); 437 throw std::runtime_error("Failed to read from " + p1.str());
438 438
439 if ((f1.gcount() == 0) && (f2.gcount() == 0)) { 439 if ((f1.gcount() == 0) && (f2.gcount() == 0)) {
440 equal = true; 440 equal = true;
441 break; 441 break;
442 } 442 }
443 443
444 if ((f1.gcount() != f2.gcount()) || 444 if ((f1.gcount() != f2.gcount()) ||
445 (std::memcmp(buf1, buf2, f1.gcount()) != 0)) { 445 (std::memcmp(buf1, buf2, f1.gcount()) != 0)) {
446 break; 446 break;
447 } 447 }
448 } 448 }
449 449
450 return equal; 450 return equal;
451} 451}
452 452
453static 453static
454void 454void
455print_diff(const atf::fs::path& p1, const atf::fs::path& p2) 455print_diff(const atf::fs::path& p1, const atf::fs::path& p2)
456{ 456{
457 const atf::process::status s = 457 const atf::process::status s =
458 atf::process::exec(atf::fs::path("diff"), 458 atf::process::exec(atf::fs::path("diff"),
459 atf::process::argv_array("diff", "-u", p1.c_str(), 459 atf::process::argv_array("diff", "-u", p1.c_str(),
460 p2.c_str(), NULL), 460 p2.c_str(), NULL),
461 atf::process::stream_connect(STDOUT_FILENO, 461 atf::process::stream_connect(STDOUT_FILENO,
462 STDERR_FILENO), 462 STDERR_FILENO),
463 atf::process::stream_inherit()); 463 atf::process::stream_inherit());
464 464
465 if (!s.exited()) 465 if (!s.exited())
466 std::cerr << "Failed to run diff(3)\n"; 466 std::cerr << "Failed to run diff(3)\n";
467 467
468 if (s.exitstatus() != 1) 468 if (s.exitstatus() != 1)
469 std::cerr << "Error while running diff(3)\n"; 469 std::cerr << "Error while running diff(3)\n";
470} 470}
471 471
472static 472static
473std::string 473std::string
474decode(const std::string& s) 474decode(const std::string& s)
475{ 475{
476 size_t i; 476 size_t i;
477 std::string res; 477 std::string res;
478 478
479 res.reserve(s.length()); 479 res.reserve(s.length());
480 480
481 i = 0; 481 i = 0;
482 while (i < s.length()) { 482 while (i < s.length()) {
483 char c = s[i++]; 483 char c = s[i++];
484 484
485 if (c == '\\') { 485 if (c == '\\') {
486 switch (s[i++]) { 486 switch (s[i++]) {
487 case 'a': c = '\a'; break; 487 case 'a': c = '\a'; break;
488 case 'b': c = '\b'; break; 488 case 'b': c = '\b'; break;
489 case 'c': break; 489 case 'c': break;
490 case 'e': c = 033; break; 490 case 'e': c = 033; break;
491 case 'f': c = '\f'; break; 491 case 'f': c = '\f'; break;
492 case 'n': c = '\n'; break; 492 case 'n': c = '\n'; break;
493 case 'r': c = '\r'; break; 493 case 'r': c = '\r'; break;
494 case 't': c = '\t'; break; 494 case 't': c = '\t'; break;
495 case 'v': c = '\v'; break; 495 case 'v': c = '\v'; break;
496 case '\\': break; 496 case '\\': break;
497 case '0': 497 case '0':
498 { 498 {
499 int count = 3; 499 int count = 3;
500 c = 0; 500 c = 0;
501 while (--count >= 0 && (unsigned)(s[i] - '0') < 8) 501 while (--count >= 0 && static_cast<unsigned>(s[i] - '0') < 8)
502 c = (c << 3) + (s[i++] - '0'); 502 c = (c << 3) + (s[i++] - '0');
503 break; 503 break;
504 } 504 }
505 default: 505 default:
506 --i; 506 --i;
507 break; 507 break;
508 } 508 }
509 } 509 }
510 510
511 res.push_back(c); 511 res.push_back(c);
512 } 512 }
513 513
514 return res; 514 return res;
515} 515}
516 516
517static 517static
518bool 518bool
519run_status_check(const status_check& sc, const atf::check::check_result& cr) 519run_status_check(const status_check& sc, const atf::check::check_result& cr)
520{ 520{
521 bool result; 521 bool result;
522 522
523 if (sc.type == sc_exit) { 523 if (sc.type == sc_exit) {
524 if (cr.exited() && sc.value != INT_MIN) { 524 if (cr.exited() && sc.value != INT_MIN) {
525 const int status = cr.exitcode(); 525 const int status = cr.exitcode();
526 526
527 if (!sc.negated && sc.value != status) { 527 if (!sc.negated && sc.value != status) {
528 std::cerr << "Fail: incorrect exit status: " 528 std::cerr << "Fail: incorrect exit status: "
529 << status << ", expected: " 529 << status << ", expected: "
530 << sc.value << "\n"; 530 << sc.value << "\n";
531 result = false; 531 result = false;
532 } else if (sc.negated && sc.value == status) { 532 } else if (sc.negated && sc.value == status) {
533 std::cerr << "Fail: incorrect exit status: " 533 std::cerr << "Fail: incorrect exit status: "
534 << status << ", expected: " 534 << status << ", expected: "
535 << "anything else\n"; 535 << "anything else\n";
536 result = false; 536 result = false;
537 } else 537 } else
538 result = true; 538 result = true;
539 } else if (cr.exited() && sc.value == INT_MIN) { 539 } else if (cr.exited() && sc.value == INT_MIN) {
540 result = true; 540 result = true;
541 } else { 541 } else {
542 std::cerr << "Fail: program did not exit cleanly\n"; 542 std::cerr << "Fail: program did not exit cleanly\n";
543 result = false; 543 result = false;
544 } 544 }
545 } else if (sc.type == sc_ignore) { 545 } else if (sc.type == sc_ignore) {
546 result = true; 546 result = true;
547 } else if (sc.type == sc_signal) { 547 } else if (sc.type == sc_signal) {
548 if (cr.signaled() && sc.value != INT_MIN) { 548 if (cr.signaled() && sc.value != INT_MIN) {
549 const int status = cr.termsig(); 549 const int status = cr.termsig();
550 550
551 if (!sc.negated && sc.value != status) { 551 if (!sc.negated && sc.value != status) {
552 std::cerr << "Fail: incorrect signal received: " 552 std::cerr << "Fail: incorrect signal received: "
553 << status << ", expected: " << sc.value << "\n"; 553 << status << ", expected: " << sc.value << "\n";
554 result = false; 554 result = false;
555 } else if (sc.negated && sc.value == status) { 555 } else if (sc.negated && sc.value == status) {
556 std::cerr << "Fail: incorrect signal received: " 556 std::cerr << "Fail: incorrect signal received: "
557 << status << ", expected: " 557 << status << ", expected: "
558 << "anything else\n"; 558 << "anything else\n";
559 result = false; 559 result = false;
560 } else 560 } else
561 result = true; 561 result = true;
562 } else if (cr.signaled() && sc.value == INT_MIN) { 562 } else if (cr.signaled() && sc.value == INT_MIN) {
563 result = true; 563 result = true;
564 } else { 564 } else {
565 std::cerr << "Fail: program did not receive a signal\n"; 565 std::cerr << "Fail: program did not receive a signal\n";
566 result = false; 566 result = false;
567 } 567 }
568 } else { 568 } else {
569 UNREACHABLE; 569 UNREACHABLE;
570 result = false; 570 result = false;
571 } 571 }
572 572
573 if (result == false) { 573 if (result == false) {
574 std::cerr << "stdout:\n"; 574 std::cerr << "stdout:\n";
575 cat_file(atf::fs::path(cr.stdout_path())); 575 cat_file(atf::fs::path(cr.stdout_path()));
576 std::cerr << "\n"; 576 std::cerr << "\n";
577 577
578 std::cerr << "stderr:\n"; 578 std::cerr << "stderr:\n";
579 cat_file(atf::fs::path(cr.stderr_path())); 579 cat_file(atf::fs::path(cr.stderr_path()));
580 std::cerr << "\n"; 580 std::cerr << "\n";
581 } 581 }
582 582
583 return result; 583 return result;
584} 584}
585 585
586static 586static
587bool 587bool
588run_status_checks(const std::vector< status_check >& checks, 588run_status_checks(const std::vector< status_check >& checks,
589 const atf::check::check_result& result) 589 const atf::check::check_result& result)
590{ 590{
591 bool ok = false; 591 bool ok = false;
592 592
593 for (std::vector< status_check >::const_iterator iter = checks.begin(); 593 for (std::vector< status_check >::const_iterator iter = checks.begin();
594 !ok && iter != checks.end(); iter++) { 594 !ok && iter != checks.end(); iter++) {
595 ok |= run_status_check(*iter, result); 595 ok |= run_status_check(*iter, result);
596 } 596 }
597 597
598 return ok; 598 return ok;
599} 599}
600 600
601static 601static
602bool 602bool
603run_output_check(const output_check oc, const atf::fs::path& path, 603run_output_check(const output_check oc, const atf::fs::path& path,
604 const std::string& stdxxx) 604 const std::string& stdxxx)
605{ 605{
606 bool result; 606 bool result;
607 607
608 if (oc.type == oc_empty) { 608 if (oc.type == oc_empty) {
609 const bool is_empty = file_empty(path); 609 const bool is_empty = file_empty(path);
610 if (!oc.negated && !is_empty) { 610 if (!oc.negated && !is_empty) {
611 std::cerr << "Fail: " << stdxxx << " not empty\n"; 611 std::cerr << "Fail: " << stdxxx << " not empty\n";
612 print_diff(atf::fs::path("/dev/null"), path); 612 print_diff(atf::fs::path("/dev/null"), path);
613 result = false; 613 result = false;
614 } else if (oc.negated && is_empty) { 614 } else if (oc.negated && is_empty) {
615 std::cerr << "Fail: " << stdxxx << " is empty\n"; 615 std::cerr << "Fail: " << stdxxx << " is empty\n";
616 result = false; 616 result = false;
617 } else 617 } else
618 result = true; 618 result = true;
619 } else if (oc.type == oc_file) { 619 } else if (oc.type == oc_file) {
620 const bool equals = compare_files(path, atf::fs::path(oc.value)); 620 const bool equals = compare_files(path, atf::fs::path(oc.value));
621 if (!oc.negated && !equals) { 621 if (!oc.negated && !equals) {
622 std::cerr << "Fail: " << stdxxx << " does not match golden " 622 std::cerr << "Fail: " << stdxxx << " does not match golden "
623 "output\n"; 623 "output\n";
624 print_diff(atf::fs::path(oc.value), path); 624 print_diff(atf::fs::path(oc.value), path);
625 result = false; 625 result = false;
626 } else if (oc.negated && equals) { 626 } else if (oc.negated && equals) {
627 std::cerr << "Fail: " << stdxxx << " matches golden output\n"; 627 std::cerr << "Fail: " << stdxxx << " matches golden output\n";
628 cat_file(atf::fs::path(oc.value)); 628 cat_file(atf::fs::path(oc.value));
629 result = false; 629 result = false;
630 } else 630 } else
631 result = true; 631 result = true;
632 } else if (oc.type == oc_ignore) { 632 } else if (oc.type == oc_ignore) {
633 result = true; 633 result = true;
634 } else if (oc.type == oc_inline) { 634 } else if (oc.type == oc_inline) {
635 atf::fs::path path2 = atf::fs::path(atf::config::get("atf_workdir")) 635 atf::fs::path path2 = atf::fs::path(atf::config::get("atf_workdir"))
636 / "inline.XXXXXX"; 636 / "inline.XXXXXX";
637 temp_file temp(path2); 637 temp_file temp(path2);
638 temp.write(decode(oc.value)); 638 temp.write(decode(oc.value));
639 temp.close(); 639 temp.close();
640 640
641 const bool equals = compare_files(path, temp.get_path()); 641 const bool equals = compare_files(path, temp.get_path());
642 if (!oc.negated && !equals) { 642 if (!oc.negated && !equals) {
643 std::cerr << "Fail: " << stdxxx << " does not match expected " 643 std::cerr << "Fail: " << stdxxx << " does not match expected "
644 "value\n"; 644 "value\n";
645 print_diff(temp.get_path(), path); 645 print_diff(temp.get_path(), path);
646 result = false; 646 result = false;
647 } else if (oc.negated && equals) { 647 } else if (oc.negated && equals) {
648 std::cerr << "Fail: " << stdxxx << " matches expected value\n"; 648 std::cerr << "Fail: " << stdxxx << " matches expected value\n";
649 cat_file(temp.get_path()); 649 cat_file(temp.get_path());
650 result = false; 650 result = false;
651 } else 651 } else
652 result = true; 652 result = true;
653 } else if (oc.type == oc_match) { 653 } else if (oc.type == oc_match) {
654 const bool matches = grep_file(path, oc.value); 654 const bool matches = grep_file(path, oc.value);
655 if (!oc.negated && !matches) { 655 if (!oc.negated && !matches) {
656 std::cerr << "Fail: regexp " + oc.value + " not in " << stdxxx 656 std::cerr << "Fail: regexp " + oc.value + " not in " << stdxxx
657 << "\n"; 657 << "\n";
658 cat_file(path); 658 cat_file(path);
659 result = false; 659 result = false;
660 } else if (oc.negated && matches) { 660 } else if (oc.negated && matches) {
661 std::cerr << "Fail: regexp " + oc.value + " is in " << stdxxx 661 std::cerr << "Fail: regexp " + oc.value + " is in " << stdxxx
662 << "\n"; 662 << "\n";
663 cat_file(path); 663 cat_file(path);
664 result = false; 664 result = false;
665 } else 665 } else
666 result = true; 666 result = true;
667 } else if (oc.type == oc_save) { 667 } else if (oc.type == oc_save) {
668 INV(!oc.negated); 668 INV(!oc.negated);
669 std::ifstream ifs(path.c_str(), std::fstream::binary); 669 std::ifstream ifs(path.c_str(), std::fstream::binary);
670 ifs >> std::noskipws; 670 ifs >> std::noskipws;
671 std::istream_iterator< char > begin(ifs), end; 671 std::istream_iterator< char > begin(ifs), end;
672 672
673 std::ofstream ofs(oc.value.c_str(), std::fstream::binary 673 std::ofstream ofs(oc.value.c_str(), std::fstream::binary
674 | std::fstream::trunc); 674 | std::fstream::trunc);
675 std::ostream_iterator <char> obegin(ofs); 675 std::ostream_iterator <char> obegin(ofs);
676 676
677 std::copy(begin, end, obegin); 677 std::copy(begin, end, obegin);
678 result = true; 678 result = true;
679 } else { 679 } else {
680 UNREACHABLE; 680 UNREACHABLE;
681 result = false; 681 result = false;
682 } 682 }
683 683
684 return result; 684 return result;
685} 685}
686 686
687static 687static
688bool 688bool
689run_output_checks(const std::vector< output_check >& checks, 689run_output_checks(const std::vector< output_check >& checks,
690 const atf::fs::path& path, const std::string& stdxxx) 690 const atf::fs::path& path, const std::string& stdxxx)
691{ 691{
692 bool ok = true; 692 bool ok = true;
693 693
694 for (std::vector< output_check >::const_iterator iter = checks.begin(); 694 for (std::vector< output_check >::const_iterator iter = checks.begin();
695 iter != checks.end(); iter++) { 695 iter != checks.end(); iter++) {
696 ok &= run_output_check(*iter, path, stdxxx); 696 ok &= run_output_check(*iter, path, stdxxx);
697 } 697 }
698 698
699 return ok; 699 return ok;
700} 700}
701 701
702// ------------------------------------------------------------------------ 702// ------------------------------------------------------------------------
703// The "atf_check" application. 703// The "atf_check" application.
704// ------------------------------------------------------------------------ 704// ------------------------------------------------------------------------
705 705
706namespace { 706namespace {
707 707
708class atf_check : public atf::application::app { 708class atf_check : public atf::application::app {
709 bool m_xflag; 709 bool m_xflag;
710 710
711 std::vector< status_check > m_status_checks; 711 std::vector< status_check > m_status_checks;
712 std::vector< output_check > m_stdout_checks; 712 std::vector< output_check > m_stdout_checks;
713 std::vector< output_check > m_stderr_checks; 713 std::vector< output_check > m_stderr_checks;
714 714
715 static const char* m_description; 715 static const char* m_description;
716 716
717 bool run_output_checks(const atf::check::check_result&, 717 bool run_output_checks(const atf::check::check_result&,
718 const std::string&) const; 718 const std::string&) const;
719 719
720 std::string specific_args(void) const; 720 std::string specific_args(void) const;
721 options_set specific_options(void) const; 721 options_set specific_options(void) const;
722 void process_option(int, const char*); 722 void process_option(int, const char*);
723 void process_option_s(const std::string&); 723 void process_option_s(const std::string&);
724 724
725public: 725public:
726 atf_check(void); 726 atf_check(void);
727 int main(void); 727 int main(void);
728}; 728};
729 729
730} // anonymous namespace 730} // anonymous namespace
731 731
732const char* atf_check::m_description = 732const char* atf_check::m_description =
733 "atf-check executes given command and analyzes its results."; 733 "atf-check executes given command and analyzes its results.";
734 734
735atf_check::atf_check(void) : 735atf_check::atf_check(void) :
736 app(m_description, "atf-check(1)"), 736 app(m_description, "atf-check(1)"),
737 m_xflag(false) 737 m_xflag(false)
738{ 738{
739} 739}
740 740
741bool 741bool
742atf_check::run_output_checks(const atf::check::check_result& r, 742atf_check::run_output_checks(const atf::check::check_result& r,
743 const std::string& stdxxx) 743 const std::string& stdxxx)
744 const 744 const
745{ 745{
746 if (stdxxx == "stdout") { 746 if (stdxxx == "stdout") {
747 return ::run_output_checks(m_stdout_checks, 747 return ::run_output_checks(m_stdout_checks,
748 atf::fs::path(r.stdout_path()), "stdout"); 748 atf::fs::path(r.stdout_path()), "stdout");
749 } else if (stdxxx == "stderr") { 749 } else if (stdxxx == "stderr") {
750 return ::run_output_checks(m_stderr_checks, 750 return ::run_output_checks(m_stderr_checks,
751 atf::fs::path(r.stderr_path()), "stderr"); 751 atf::fs::path(r.stderr_path()), "stderr");
752 } else { 752 } else {
753 UNREACHABLE; 753 UNREACHABLE;
754 return false; 754 return false;
755 } 755 }
756} 756}
757 757
758std::string 758std::string
759atf_check::specific_args(void) 759atf_check::specific_args(void)
760 const 760 const
761{ 761{
762 return "<command>"; 762 return "<command>";
763} 763}
764 764
765atf_check::options_set 765atf_check::options_set
766atf_check::specific_options(void) 766atf_check::specific_options(void)
767 const 767 const
768{ 768{
769 using atf::application::option; 769 using atf::application::option;
770 options_set opts; 770 options_set opts;
771 771
772 opts.insert(option('s', "qual:value", "Handle status. Qualifier " 772 opts.insert(option('s', "qual:value", "Handle status. Qualifier "
773 "must be one of: ignore exit:<num> signal:<name|num>")); 773 "must be one of: ignore exit:<num> signal:<name|num>"));
774 opts.insert(option('o', "action:arg", "Handle stdout. Action must be " 774 opts.insert(option('o', "action:arg", "Handle stdout. Action must be "
775 "one of: empty ignore file:<path> inline:<val> match:regexp " 775 "one of: empty ignore file:<path> inline:<val> match:regexp "
776 "save:<path>")); 776 "save:<path>"));
777 opts.insert(option('e', "action:arg", "Handle stderr. Action must be " 777 opts.insert(option('e', "action:arg", "Handle stderr. Action must be "
778 "one of: empty ignore file:<path> inline:<val> match:regexp " 778 "one of: empty ignore file:<path> inline:<val> match:regexp "
779 "save:<path>")); 779 "save:<path>"));
780 opts.insert(option('x', "", "Execute command as a shell command")); 780 opts.insert(option('x', "", "Execute command as a shell command"));
781 781
782 return opts; 782 return opts;
783} 783}
784 784
785void 785void
786atf_check::process_option(int ch, const char* arg) 786atf_check::process_option(int ch, const char* arg)
787{ 787{
788 switch (ch) { 788 switch (ch) {
789 case 's': 789 case 's':
790 m_status_checks.push_back(parse_status_check_arg(arg)); 790 m_status_checks.push_back(parse_status_check_arg(arg));
791 break; 791 break;
792 792
793 case 'o': 793 case 'o':
794 m_stdout_checks.push_back(parse_output_check_arg(arg)); 794 m_stdout_checks.push_back(parse_output_check_arg(arg));
795 break; 795 break;
796 796
797 case 'e': 797 case 'e':
798 m_stderr_checks.push_back(parse_output_check_arg(arg)); 798 m_stderr_checks.push_back(parse_output_check_arg(arg));
799 break; 799 break;
800 800
801 case 'x': 801 case 'x':
802 m_xflag = true; 802 m_xflag = true;
803 break; 803 break;
804 804
805 default: 805 default:
806 UNREACHABLE; 806 UNREACHABLE;
807 } 807 }
808} 808}
809 809
810int 810int
811atf_check::main(void) 811atf_check::main(void)
812{ 812{
813 if (m_argc < 1) 813 if (m_argc < 1)
814 throw atf::application::usage_error("No command specified"); 814 throw atf::application::usage_error("No command specified");
815 815
816 int status = EXIT_FAILURE; 816 int status = EXIT_FAILURE;
817 817
818 std::auto_ptr< atf::check::check_result > r = 818 std::auto_ptr< atf::check::check_result > r =
819 m_xflag ? execute_with_shell(m_argv) : execute(m_argv); 819 m_xflag ? execute_with_shell(m_argv) : execute(m_argv);
820 820
821 if (m_status_checks.empty()) 821 if (m_status_checks.empty())
822 m_status_checks.push_back(status_check(sc_exit, false, EXIT_SUCCESS)); 822 m_status_checks.push_back(status_check(sc_exit, false, EXIT_SUCCESS));
823 else if (m_status_checks.size() > 1) { 823 else if (m_status_checks.size() > 1) {
824 // TODO: Remove this restriction. 824 // TODO: Remove this restriction.
825 throw atf::application::usage_error("Cannot specify -s more than once"); 825 throw atf::application::usage_error("Cannot specify -s more than once");
826 } 826 }
827 827
828 if (m_stdout_checks.empty()) 828 if (m_stdout_checks.empty())
829 m_stdout_checks.push_back(output_check(oc_empty, false, "")); 829 m_stdout_checks.push_back(output_check(oc_empty, false, ""));
830 if (m_stderr_checks.empty()) 830 if (m_stderr_checks.empty())
831 m_stderr_checks.push_back(output_check(oc_empty, false, "")); 831 m_stderr_checks.push_back(output_check(oc_empty, false, ""));
832 832
833 if ((run_status_checks(m_status_checks, *r) == false) || 833 if ((run_status_checks(m_status_checks, *r) == false) ||
834 (run_output_checks(*r, "stderr") == false) || 834 (run_output_checks(*r, "stderr") == false) ||
835 (run_output_checks(*r, "stdout") == false)) 835 (run_output_checks(*r, "stdout") == false))
836 status = EXIT_FAILURE; 836 status = EXIT_FAILURE;
837 else 837 else
838 status = EXIT_SUCCESS; 838 status = EXIT_SUCCESS;
839 839
840 return status; 840 return status;
841} 841}
842 842
843int 843int
844main(int argc, char* const* argv) 844main(int argc, char* const* argv)
845{ 845{
846 return atf_check().run(argc, argv); 846 return atf_check().run(argc, argv);
847} 847}

cvs diff -r1.5 -r1.6 src/external/bsd/atf/dist/tools/process.cpp (switch to unified diff)

--- src/external/bsd/atf/dist/tools/process.cpp 2018/02/04 01:41:05 1.5
+++ src/external/bsd/atf/dist/tools/process.cpp 2019/10/09 01:18:55 1.6
@@ -1,510 +1,509 @@ @@ -1,510 +1,509 @@
1// 1//
2// Automated Testing Framework (atf) 2// Automated Testing Framework (atf)
3// 3//
4// Copyright (c) 2008 The NetBSD Foundation, Inc. 4// Copyright (c) 2008 The NetBSD Foundation, Inc.
5// All rights reserved. 5// All rights reserved.
6// 6//
7// Redistribution and use in source and binary forms, with or without 7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions 8// modification, are permitted provided that the following conditions
9// are met: 9// are met:
10// 1. Redistributions of source code must retain the above copyright 10// 1. Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer. 11// notice, this list of conditions and the following disclaimer.
12// 2. Redistributions in binary form must reproduce the above copyright 12// 2. Redistributions in binary form must reproduce the above copyright
13// notice, this list of conditions and the following disclaimer in the 13// notice, this list of conditions and the following disclaimer in the
14// documentation and/or other materials provided with the distribution. 14// documentation and/or other materials provided with the distribution.
15// 15//
16// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 16// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 20// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28// 28//
29 29
30extern "C" { 30extern "C" {
31#include <sys/types.h> 31#include <sys/types.h>
32#include <sys/wait.h> 32#include <sys/wait.h>
33 33
34#include <fcntl.h> 34#include <fcntl.h>
35#include <signal.h> 35#include <signal.h>
36} 36}
37 37
38#include <cassert> 38#include <cassert>
39#include <cstdarg> 39#include <cstdarg>
40#include <cerrno> 40#include <cerrno>
41#include <cstring> 41#include <cstring>
42#include <iostream> 42#include <iostream>
43 43
44#include "exceptions.hpp" 44#include "exceptions.hpp"
45#include "text.hpp" 45#include "text.hpp"
46#include "process.hpp" 46#include "process.hpp"
47 47
48namespace detail = tools::process::detail; 48namespace detail = tools::process::detail;
49namespace impl = tools::process; 49namespace impl = tools::process;
50#define IMPL_NAME "tools::process" 50#define IMPL_NAME "tools::process"
51 51
52// ------------------------------------------------------------------------ 52// ------------------------------------------------------------------------
53// Auxiliary functions. 53// Auxiliary functions.
54// ------------------------------------------------------------------------ 54// ------------------------------------------------------------------------
55 55
56template< class C > 56template< class C >
57tools::auto_array< const char* > 57tools::auto_array< const char* >
58collection_to_argv(const C& c) 58collection_to_argv(const C& c)
59{ 59{
60 tools::auto_array< const char* > argv(new const char*[c.size() + 1]); 60 tools::auto_array< const char* > argv(new const char*[c.size() + 1]);
61 61
62 std::size_t pos = 0; 62 std::size_t pos = 0;
63 for (typename C::const_iterator iter = c.begin(); iter != c.end(); 63 for (typename C::const_iterator iter = c.begin(); iter != c.end();
64 iter++) { 64 iter++) {
65 argv[pos] = (*iter).c_str(); 65 argv[pos] = (*iter).c_str();
66 pos++; 66 pos++;
67 } 67 }
68 assert(pos == c.size()); 68 assert(pos == c.size());
69 argv[pos] = NULL; 69 argv[pos] = NULL;
70 70
71 return argv; 71 return argv;
72} 72}
73 73
74template< class C > 74template< class C >
75C 75C
76argv_to_collection(const char* const* argv) 76argv_to_collection(const char* const* argv)
77{ 77{
78 C c; 78 C c;
79 79
80 for (const char* const* iter = argv; *iter != NULL; iter++) 80 for (const char* const* iter = argv; *iter != NULL; iter++)
81 c.push_back(std::string(*iter)); 81 c.push_back(std::string(*iter));
82 82
83 return c; 83 return c;
84} 84}
85 85
86static 86static
87void 87void
88safe_dup(const int oldfd, const int newfd) 88safe_dup(const int oldfd, const int newfd)
89{ 89{
90 if (oldfd != newfd) { 90 if (oldfd != newfd) {
91 if (dup2(oldfd, newfd) == -1) { 91 if (dup2(oldfd, newfd) == -1) {
92 throw tools::system_error(IMPL_NAME "::safe_dup", 92 throw tools::system_error(IMPL_NAME "::safe_dup",
93 "Could not allocate file descriptor", 93 "Could not allocate file descriptor",
94 errno); 94 errno);
95 } else { 95 } else {
96 ::close(oldfd); 96 ::close(oldfd);
97 } 97 }
98 } 98 }
99} 99}
100 100
101static 101static
102int 102int
103const_execvp(const char *file, const char *const *argv) 103const_execvp(const char *file, const char *const *argv)
104{ 104{
105#define UNCONST(a) ((void *)(unsigned long)(const void *)(a)) 105 return ::execvp(file, const_cast<char* const*>(argv));
106 return ::execvp(file, (char* const*)(UNCONST(argv))); 
107#undef UNCONST 106#undef UNCONST
108} 107}
109 108
110void 109void
111detail::do_exec(void *v) 110detail::do_exec(void *v)
112{ 111{
113 struct exec_args *ea = reinterpret_cast<struct exec_args *>(v); 112 struct exec_args *ea = reinterpret_cast<struct exec_args *>(v);
114 113
115 if (ea->m_prehook != NULL) 114 if (ea->m_prehook != NULL)
116 ea->m_prehook(); 115 ea->m_prehook();
117 116
118 const int ret = const_execvp(ea->m_prog.c_str(), ea->m_argv.exec_argv()); 117 const int ret = const_execvp(ea->m_prog.c_str(), ea->m_argv.exec_argv());
119 const int errnocopy = errno; 118 const int errnocopy = errno;
120 assert(ret == -1); 119 assert(ret == -1);
121 std::cerr << "exec(" << ea->m_prog.str() << ") failed: " 120 std::cerr << "exec(" << ea->m_prog.str() << ") failed: "
122 << std::strerror(errnocopy) << "\n"; 121 << std::strerror(errnocopy) << "\n";
123 std::exit(EXIT_FAILURE); 122 std::exit(EXIT_FAILURE);
124} 123}
125 124
126// ------------------------------------------------------------------------ 125// ------------------------------------------------------------------------
127// The "argv_array" type. 126// The "argv_array" type.
128// ------------------------------------------------------------------------ 127// ------------------------------------------------------------------------
129 128
130impl::argv_array::argv_array(void) : 129impl::argv_array::argv_array(void) :
131 m_exec_argv(collection_to_argv(m_args)) 130 m_exec_argv(collection_to_argv(m_args))
132{ 131{
133} 132}
134 133
135impl::argv_array::argv_array(const char* arg1, ...) 134impl::argv_array::argv_array(const char* arg1, ...)
136{ 135{
137 m_args.push_back(arg1); 136 m_args.push_back(arg1);
138 137
139 { 138 {
140 va_list ap; 139 va_list ap;
141 const char* nextarg; 140 const char* nextarg;
142 141
143 va_start(ap, arg1); 142 va_start(ap, arg1);
144 while ((nextarg = va_arg(ap, const char*)) != NULL) 143 while ((nextarg = va_arg(ap, const char*)) != NULL)
145 m_args.push_back(nextarg); 144 m_args.push_back(nextarg);
146 va_end(ap); 145 va_end(ap);
147 } 146 }
148 147
149 ctor_init_exec_argv(); 148 ctor_init_exec_argv();
150} 149}
151 150
152impl::argv_array::argv_array(const char* const* ca) : 151impl::argv_array::argv_array(const char* const* ca) :
153 m_args(argv_to_collection< args_vector >(ca)), 152 m_args(argv_to_collection< args_vector >(ca)),
154 m_exec_argv(collection_to_argv(m_args)) 153 m_exec_argv(collection_to_argv(m_args))
155{ 154{
156} 155}
157 156
158impl::argv_array::argv_array(const argv_array& a) : 157impl::argv_array::argv_array(const argv_array& a) :
159 m_args(a.m_args), 158 m_args(a.m_args),
160 m_exec_argv(collection_to_argv(m_args)) 159 m_exec_argv(collection_to_argv(m_args))
161{ 160{
162} 161}
163 162
164void 163void
165impl::argv_array::ctor_init_exec_argv(void) 164impl::argv_array::ctor_init_exec_argv(void)
166{ 165{
167 m_exec_argv = collection_to_argv(m_args); 166 m_exec_argv = collection_to_argv(m_args);
168} 167}
169 168
170const char* const* 169const char* const*
171impl::argv_array::exec_argv(void) 170impl::argv_array::exec_argv(void)
172 const 171 const
173{ 172{
174 return m_exec_argv.get(); 173 return m_exec_argv.get();
175} 174}
176 175
177impl::argv_array::size_type 176impl::argv_array::size_type
178impl::argv_array::size(void) 177impl::argv_array::size(void)
179 const 178 const
180{ 179{
181 return m_args.size(); 180 return m_args.size();
182} 181}
183 182
184const char* 183const char*
185impl::argv_array::operator[](int idx) 184impl::argv_array::operator[](int idx)
186 const 185 const
187{ 186{
188 return m_args[idx].c_str(); 187 return m_args[idx].c_str();
189} 188}
190 189
191impl::argv_array::const_iterator 190impl::argv_array::const_iterator
192impl::argv_array::begin(void) 191impl::argv_array::begin(void)
193 const 192 const
194{ 193{
195 return m_args.begin(); 194 return m_args.begin();
196} 195}
197 196
198impl::argv_array::const_iterator 197impl::argv_array::const_iterator
199impl::argv_array::end(void) 198impl::argv_array::end(void)
200 const 199 const
201{ 200{
202 return m_args.end(); 201 return m_args.end();
203} 202}
204 203
205impl::argv_array& 204impl::argv_array&
206impl::argv_array::operator=(const argv_array& a) 205impl::argv_array::operator=(const argv_array& a)
207{ 206{
208 if (this != &a) { 207 if (this != &a) {
209 m_args = a.m_args; 208 m_args = a.m_args;
210 m_exec_argv = collection_to_argv(m_args); 209 m_exec_argv = collection_to_argv(m_args);
211 } 210 }
212 return *this; 211 return *this;
213} 212}
214 213
215// ------------------------------------------------------------------------ 214// ------------------------------------------------------------------------
216// The "stream" types. 215// The "stream" types.
217// ------------------------------------------------------------------------ 216// ------------------------------------------------------------------------
218 217
219impl::stream_capture::stream_capture(void) 218impl::stream_capture::stream_capture(void)
220{ 219{
221 for (int i = 0; i < 2; i++) 220 for (int i = 0; i < 2; i++)
222 m_pipefds[i] = -1; 221 m_pipefds[i] = -1;
223} 222}
224 223
225impl::stream_capture::~stream_capture(void) 224impl::stream_capture::~stream_capture(void)
226{ 225{
227 for (int i = 0; i < 2; i++) 226 for (int i = 0; i < 2; i++)
228 if (m_pipefds[i] != -1) 227 if (m_pipefds[i] != -1)
229 ::close(m_pipefds[i]); 228 ::close(m_pipefds[i]);
230} 229}
231 230
232void 231void
233impl::stream_capture::prepare(void) 232impl::stream_capture::prepare(void)
234{ 233{
235 if (pipe(m_pipefds) == -1) 234 if (pipe(m_pipefds) == -1)
236 throw system_error(IMPL_NAME "::stream_capture::prepare", 235 throw system_error(IMPL_NAME "::stream_capture::prepare",
237 "Failed to create pipe", errno); 236 "Failed to create pipe", errno);
238} 237}
239 238
240int 239int
241impl::stream_capture::connect_parent(void) 240impl::stream_capture::connect_parent(void)
242{ 241{
243 ::close(m_pipefds[1]); m_pipefds[1] = -1; 242 ::close(m_pipefds[1]); m_pipefds[1] = -1;
244 const int fd = m_pipefds[0]; 243 const int fd = m_pipefds[0];
245 m_pipefds[0] = -1; 244 m_pipefds[0] = -1;
246 return fd; 245 return fd;
247} 246}
248 247
249void 248void
250impl::stream_capture::connect_child(const int fd) 249impl::stream_capture::connect_child(const int fd)
251{ 250{
252 ::close(m_pipefds[0]); m_pipefds[0] = -1; 251 ::close(m_pipefds[0]); m_pipefds[0] = -1;
253 if (m_pipefds[1] != fd) { 252 if (m_pipefds[1] != fd) {
254 safe_dup(m_pipefds[1], fd); 253 safe_dup(m_pipefds[1], fd);
255 } 254 }
256 m_pipefds[1] = -1; 255 m_pipefds[1] = -1;
257} 256}
258 257
259impl::stream_connect::stream_connect(const int src_fd, const int tgt_fd) : 258impl::stream_connect::stream_connect(const int src_fd, const int tgt_fd) :
260 m_src_fd(src_fd), m_tgt_fd(tgt_fd) 259 m_src_fd(src_fd), m_tgt_fd(tgt_fd)
261{ 260{
262} 261}
263 262
264void 263void
265impl::stream_connect::prepare(void) 264impl::stream_connect::prepare(void)
266{ 265{
267} 266}
268 267
269int 268int
270impl::stream_connect::connect_parent(void) 269impl::stream_connect::connect_parent(void)
271{ 270{
272 return -1; 271 return -1;
273} 272}
274 273
275void 274void
276impl::stream_connect::connect_child(const int fd __attribute__((__unused__))) 275impl::stream_connect::connect_child(const int fd __attribute__((__unused__)))
277{ 276{
278 safe_dup(m_tgt_fd, m_src_fd); 277 safe_dup(m_tgt_fd, m_src_fd);
279} 278}
280 279
281impl::stream_inherit::stream_inherit(void) 280impl::stream_inherit::stream_inherit(void)
282{ 281{
283} 282}
284 283
285void 284void
286impl::stream_inherit::prepare(void) 285impl::stream_inherit::prepare(void)
287{ 286{
288} 287}
289 288
290int 289int
291impl::stream_inherit::connect_parent(void) 290impl::stream_inherit::connect_parent(void)
292{ 291{
293 return -1; 292 return -1;
294} 293}
295 294
296void 295void
297impl::stream_inherit::connect_child(const int fd __attribute__((__unused__))) 296impl::stream_inherit::connect_child(const int fd __attribute__((__unused__)))
298{ 297{
299} 298}
300 299
301impl::stream_redirect_fd::stream_redirect_fd(const int fd) : 300impl::stream_redirect_fd::stream_redirect_fd(const int fd) :
302 m_fd(fd) 301 m_fd(fd)
303{ 302{
304} 303}
305 304
306void 305void
307impl::stream_redirect_fd::prepare(void) 306impl::stream_redirect_fd::prepare(void)
308{ 307{
309} 308}
310 309
311int 310int
312impl::stream_redirect_fd::connect_parent(void) 311impl::stream_redirect_fd::connect_parent(void)
313{ 312{
314 return -1; 313 return -1;
315} 314}
316 315
317void 316void
318impl::stream_redirect_fd::connect_child(const int fd) 317impl::stream_redirect_fd::connect_child(const int fd)
319{ 318{
320 safe_dup(m_fd, fd); 319 safe_dup(m_fd, fd);
321} 320}
322 321
323impl::stream_redirect_path::stream_redirect_path(const tools::fs::path& p) : 322impl::stream_redirect_path::stream_redirect_path(const tools::fs::path& p) :
324 m_path(p) 323 m_path(p)
325{ 324{
326} 325}
327 326
328void 327void
329impl::stream_redirect_path::prepare(void) 328impl::stream_redirect_path::prepare(void)
330{ 329{
331} 330}
332 331
333int 332int
334impl::stream_redirect_path::connect_parent(void) 333impl::stream_redirect_path::connect_parent(void)
335{ 334{
336 return -1; 335 return -1;
337} 336}
338 337
339void 338void
340impl::stream_redirect_path::connect_child(const int fd) 339impl::stream_redirect_path::connect_child(const int fd)
341{ 340{
342 const int aux = ::open(m_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644); 341 const int aux = ::open(m_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
343 if (aux == -1) 342 if (aux == -1)
344 throw system_error(IMPL_NAME "::stream_redirect_path::connect_child", 343 throw system_error(IMPL_NAME "::stream_redirect_path::connect_child",
345 "Could not create " + m_path.str(), errno); 344 "Could not create " + m_path.str(), errno);
346 else 345 else
347 safe_dup(aux, fd); 346 safe_dup(aux, fd);
348} 347}
349 348
350// ------------------------------------------------------------------------ 349// ------------------------------------------------------------------------
351// The "status" type. 350// The "status" type.
352// ------------------------------------------------------------------------ 351// ------------------------------------------------------------------------
353 352
354impl::status::status(int s) : 353impl::status::status(int s) :
355 m_status(s) 354 m_status(s)
356{ 355{
357} 356}
358 357
359impl::status::~status(void) 358impl::status::~status(void)
360{ 359{
361} 360}
362 361
363std::string 362std::string
364impl::status::str(void) 363impl::status::str(void)
365 const 364 const
366{ 365{
367 int mutable_status = m_status; 366 int mutable_status = m_status;
368 std::stringstream rv; 367 std::stringstream rv;
369 if (WIFEXITED(mutable_status)) 368 if (WIFEXITED(mutable_status))
370 rv << "exit(" << WEXITSTATUS(mutable_status); 369 rv << "exit(" << WEXITSTATUS(mutable_status);
371 else if (WIFSTOPPED(mutable_status)) 370 else if (WIFSTOPPED(mutable_status))
372 rv << "stopped(" << WSTOPSIG(mutable_status); 371 rv << "stopped(" << WSTOPSIG(mutable_status);
373 else if (WIFSIGNALED(mutable_status)) 372 else if (WIFSIGNALED(mutable_status))
374 rv << "terminated(" << WTERMSIG(mutable_status); 373 rv << "terminated(" << WTERMSIG(mutable_status);
375 if (WCOREDUMP(mutable_status)) 374 if (WCOREDUMP(mutable_status))
376 rv << "/core)"; 375 rv << "/core)";
377 else 376 else
378 rv << ")"; 377 rv << ")";
379 return rv.str(); 378 return rv.str();
380} 379}
381 380
382bool 381bool
383impl::status::exited(void) 382impl::status::exited(void)
384 const 383 const
385{ 384{
386 int mutable_status = m_status; 385 int mutable_status = m_status;
387 return WIFEXITED(mutable_status); 386 return WIFEXITED(mutable_status);
388} 387}
389 388
390int 389int
391impl::status::exitstatus(void) 390impl::status::exitstatus(void)
392 const 391 const
393{ 392{
394 assert(exited()); 393 assert(exited());
395 int mutable_status = m_status; 394 int mutable_status = m_status;
396 return WEXITSTATUS(mutable_status); 395 return WEXITSTATUS(mutable_status);
397} 396}
398 397
399bool 398bool
400impl::status::signaled(void) 399impl::status::signaled(void)
401 const 400 const
402{ 401{
403 int mutable_status = m_status; 402 int mutable_status = m_status;
404 return WIFSIGNALED(mutable_status); 403 return WIFSIGNALED(mutable_status);
405} 404}
406 405
407int 406int
408impl::status::termsig(void) 407impl::status::termsig(void)
409 const 408 const
410{ 409{
411 assert(signaled()); 410 assert(signaled());
412 int mutable_status = m_status; 411 int mutable_status = m_status;
413 return WTERMSIG(mutable_status); 412 return WTERMSIG(mutable_status);
414} 413}
415 414
416bool 415bool
417impl::status::coredump(void) 416impl::status::coredump(void)
418 const 417 const
419{ 418{
420 assert(signaled()); 419 assert(signaled());
421 int mutable_status = m_status; 420 int mutable_status = m_status;
422 return WCOREDUMP(mutable_status); 421 return WCOREDUMP(mutable_status);
423} 422}
424 423
425// ------------------------------------------------------------------------ 424// ------------------------------------------------------------------------
426// The "child" type. 425// The "child" type.
427// ------------------------------------------------------------------------ 426// ------------------------------------------------------------------------
428 427
429impl::child::child(const pid_t pid_arg, const int stdout_fd_arg, 428impl::child::child(const pid_t pid_arg, const int stdout_fd_arg,
430 const int stderr_fd_arg) : 429 const int stderr_fd_arg) :
431 m_pid(pid_arg), 430 m_pid(pid_arg),
432 m_stdout(stdout_fd_arg), 431 m_stdout(stdout_fd_arg),
433 m_stderr(stderr_fd_arg), 432 m_stderr(stderr_fd_arg),
434 m_waited(false) 433 m_waited(false)
435{ 434{
436} 435}
437 436
438impl::child::~child(void) 437impl::child::~child(void)
439{ 438{
440 if (!m_waited) { 439 if (!m_waited) {
441 ::kill(m_pid, SIGTERM); 440 ::kill(m_pid, SIGTERM);
442 (void)wait(); 441 (void)wait();
443 442
444 if (m_stdout != -1) { 443 if (m_stdout != -1) {
445 ::close(m_stdout); m_stdout = -1; 444 ::close(m_stdout); m_stdout = -1;
446 } 445 }
447 if (m_stderr != -1) { 446 if (m_stderr != -1) {
448 ::close(m_stderr); m_stderr = -1; 447 ::close(m_stderr); m_stderr = -1;
449 } 448 }
450 } 449 }
451} 450}
452 451
453impl::status 452impl::status
454impl::child::wait(void) 453impl::child::wait(void)
455{ 454{
456 int s; 455 int s;
457 456
458 if (::waitpid(m_pid, &s, 0) == -1) 457 if (::waitpid(m_pid, &s, 0) == -1)
459 throw system_error(IMPL_NAME "::child::wait", "Failed waiting for " 458 throw system_error(IMPL_NAME "::child::wait", "Failed waiting for "
460 "process " + text::to_string(m_pid), errno); 459 "process " + text::to_string(m_pid), errno);
461 460
462 if (m_stdout != -1) { 461 if (m_stdout != -1) {
463 ::close(m_stdout); m_stdout = -1; 462 ::close(m_stdout); m_stdout = -1;
464 } 463 }
465 if (m_stderr != -1) { 464 if (m_stderr != -1) {
466 ::close(m_stderr); m_stderr = -1; 465 ::close(m_stderr); m_stderr = -1;
467 } 466 }
468 467
469 m_waited = true; 468 m_waited = true;
470 return status(s); 469 return status(s);
471} 470}
472 471
473pid_t 472pid_t
474impl::child::pid(void) 473impl::child::pid(void)
475 const 474 const
476{ 475{
477 return m_pid; 476 return m_pid;
478} 477}
479 478
480int 479int
481impl::child::stdout_fd(void) 480impl::child::stdout_fd(void)
482{ 481{
483 return m_stdout; 482 return m_stdout;
484} 483}
485 484
486int 485int
487impl::child::stderr_fd(void) 486impl::child::stderr_fd(void)
488{ 487{
489 return m_stderr; 488 return m_stderr;
490} 489}
491 490
492// ------------------------------------------------------------------------ 491// ------------------------------------------------------------------------
493// Free functions. 492// Free functions.
494// ------------------------------------------------------------------------ 493// ------------------------------------------------------------------------
495 494
496void 495void
497detail::flush_streams(void) 496detail::flush_streams(void)
498{ 497{
499 // This is a weird hack to ensure that the output of the parent process 498 // This is a weird hack to ensure that the output of the parent process
500 // is flushed before executing a child which prevents, for example, the 499 // is flushed before executing a child which prevents, for example, the
501 // output of the atf-run hooks to appear before the output of atf-run 500 // output of the atf-run hooks to appear before the output of atf-run
502 // itself. 501 // itself.
503 // 502 //
504 // TODO: This should only be executed when inheriting the stdout or 503 // TODO: This should only be executed when inheriting the stdout or
505 // stderr file descriptors. However, the flushing is specific to the 504 // stderr file descriptors. However, the flushing is specific to the
506 // iostreams, so we cannot do it from the C library where all the process 505 // iostreams, so we cannot do it from the C library where all the process
507 // logic is performed. Come up with a better design. 506 // logic is performed. Come up with a better design.
508 std::cout.flush(); 507 std::cout.flush();
509 std::cerr.flush(); 508 std::cerr.flush();
510} 509}