Apache Mesos
shell.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_OS_SHELL_HPP__
14 #define __STOUT_OS_SHELL_HPP__
15 
16 // For readability, we minimize the number of #ifdef blocks in the code by
17 // splitting platform specific system calls into separate directories.
18 #ifdef __WINDOWS__
20 #else
21 #include <stout/os/posix/shell.hpp>
22 #endif // __WINDOWS__
23 
24 namespace os {
25 
26 // Executes a shell command (formatted in an sprintf manner) in a subprocess.
27 //
28 // Blocks until the subprocess terminates and returns the stdout
29 // (but not stderr!) from running the specified command with the
30 // shell; or an error message if the command's exit code is non-zero
31 // or the process exited from a signal.
32 //
33 // POSIX: Performs a `popen(command.c_str(), "r")` and reads the
34 // output until EOF or reading fails. Note that this is not an
35 // async signal safe function.
36 //
37 // Windows: Forks and executes a "cmd /c <command>" subprocess.
38 // TODO(bmahler): Rather than passing the command string to cmd /c,
39 // this function is incorrectly quoting / escaping it as if it's
40 // executing a program compatible with `CommandLineToArgvW`. cmd.exe
41 // Does not use `CommandLineToArgvW` and has its own parsing, which
42 // means we should not be adding extra quoting and the caller should
43 // make sure that the command is correctly escaped. See MESOS-10093.
44 //
45 // Note: Be cautious about shell injection
46 // (https://en.wikipedia.org/wiki/Code_injection#Shell_injection)
47 // when using this method and use proper validation and sanitization
48 // on the `command`. For this reason in general directly executing the
49 // program using `os::spawn` is preferred if a shell is not required.
50 //
51 // TODO(bmahler): Embedding string formatting leads to a confusing
52 // interface, why don't we let callers decide how they want to format
53 // the command string?
54 template <typename... T>
55 Try<std::string> shell(const std::string& fmt, const T&... t);
56 
57 
58 // Executes a shell command in a subprocess.
59 //
60 // Blocks until the subprocess terminates and returns the exit code of
61 // the subprocess, or `None` if an error occurred (e.g., fork / exec /
62 // waitpid or the Windows equivalents failed).
63 //
64 // POSIX: Performs a `fork()` / `execlp("sh", "-c", command, (char*)0)`
65 // in an async signal safe manner. Note that this is not a pure wrapper
66 // of the POSIX `system` call because the POSIX implementation ignores
67 // SIGINT/SIGQUIT and blocks SIGCHLD while waiting for the child to
68 // complete (which is not async-signal-safe).
69 //
70 // Windows: Forks and executes a "cmd /c <command>" subprocess.
71 // TODO(bmahler): Rather than passing the command string to cmd /c,
72 // this function is incorrectly quoting / escaping it as if it's
73 // executing a program compatible with `CommandLineToArgvW`. cmd.exe
74 // Does not use `CommandLineToArgvW` and has its own parsing, which
75 // means we should not be adding extra quoting and the caller should
76 // make sure that the command is correctly escaped. See MESOS-10093.
77 //
78 // Note: Be cautious about shell injection
79 // (https://en.wikipedia.org/wiki/Code_injection#Shell_injection)
80 // when using this method and use proper validation and sanitization
81 // on the `command`. For this reason in general directly executing the
82 // program using `os::spawn` is preferred if a shell is not required.
83 //
84 // Note that the return type is `Option<int>` rather than `Try<int>`
85 // because `Error` uses an std::string which is not async signal safe.
86 inline Option<int> system(const std::string& command);
87 
88 } // namespace os {
89 
90 #endif // __STOUT_OS_SHELL_HPP__
Definition: check.hpp:33
Definition: posix_signalhandler.hpp:23
Try< std::string > shell(const std::string &fmt, const T &...t)
Definition: shell.hpp:49
Option< int > system(const std::string &command)
Definition: shell.hpp:97