2 // Automated Testing Framework (atf)
4 // Copyright (c) 2010 The NetBSD Foundation, Inc.
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
10 // 1. Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // 2. Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include "atf-c++/config.hpp"
41 #include "atf-c++/detail/application.hpp"
42 #include "atf-c++/detail/fs.hpp"
43 #include "atf-c++/detail/sanity.hpp"
45 // ------------------------------------------------------------------------
46 // Auxiliary functions.
47 // ------------------------------------------------------------------------
53 fix_plain_name(const char *filename
)
55 const atf::fs::path
filepath(filename
);
56 if (filepath
.branch_path().str() == ".")
57 return std::string("./") + filename
;
59 return std::string(filename
);
64 construct_script(const char* filename
)
66 const std::string libexecdir
= atf::config::get("atf_libexecdir");
67 const std::string pkgdatadir
= atf::config::get("atf_pkgdatadir");
68 const std::string shell
= atf::config::get("atf_shell");
70 std::string
* command
= new std::string();
71 command
->reserve(512);
72 (*command
) += ("Atf_Check='" + libexecdir
+ "/atf-check' ; " +
73 "Atf_Shell='" + shell
+ "' ; " +
74 ". " + pkgdatadir
+ "/libatf-sh.subr ; " +
75 ". " + fix_plain_name(filename
) + " ; " +
82 construct_argv(const std::string
& shell
, const int interpreter_argc
,
83 const char* const* interpreter_argv
)
85 PRE(interpreter_argc
>= 1);
86 PRE(interpreter_argv
[0] != NULL
);
88 const std::string
* script
= construct_script(interpreter_argv
[0]);
90 const int count
= 4 + (interpreter_argc
- 1) + 1;
91 const char** argv
= new const char*[count
];
92 argv
[0] = shell
.c_str();
94 argv
[2] = script
->c_str();
95 argv
[3] = interpreter_argv
[0];
97 for (int i
= 1; i
< interpreter_argc
; i
++)
98 argv
[4 + i
- 1] = interpreter_argv
[i
];
100 argv
[count
- 1] = NULL
;
105 } // anonymous namespace
107 // ------------------------------------------------------------------------
108 // The "atf_sh" class.
109 // ------------------------------------------------------------------------
111 class atf_sh
: public atf::application::app
{
112 static const char* m_description
;
120 const char* atf_sh::m_description
=
121 "atf-sh is a shell interpreter that extends the functionality of the "
122 "system sh(1) with the atf-sh library.";
124 atf_sh::atf_sh(void) :
125 app(m_description
, "atf-sh(1)", "atf(7)")
133 throw atf::application::usage_error("No test program provided");
135 const atf::fs::path
script(m_argv
[0]);
136 if (!atf::fs::exists(script
))
137 throw std::runtime_error("The test program '" + script
.str() + "' "
140 const std::string shell
= atf::config::get("atf_shell");
141 const char** argv
= construct_argv(shell
, m_argc
, m_argv
);
142 // Don't bother keeping track of the memory allocated by construct_argv:
143 // we are going to exec or die immediately.
145 const int ret
= execv(shell
.c_str(), const_cast< char** >(argv
));
147 std::cerr
<< "Failed to execute " << shell
<< ": " << std::strerror(errno
)
153 main(int argc
, char* const* argv
)
155 return atf_sh().run(argc
, argv
);