StormByte-System 2.0.0
C++26 process and environment module of the StormByte suite
 
Loading...
Searching...
No Matches
process.hxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2024-2026 David C. Manuelda (StormBytePP)
3 *
4 * This file is part of StormByte-System.
5 *
6 * StormByte-System original source is dual-licensed:
7 *
8 * 1. GNU Lesser General Public License v3.0 (or later)
9 * You may redistribute and/or modify this file under the terms of the
10 * GNU Lesser General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option)
12 * any later version.
13 *
14 * 2. Commercial license
15 * Alternatively, this file may be used under the terms of a commercial
16 * license agreement with the copyright holder
17 * (David C. Manuelda <StormByte@gmail.com>).
18 *
19 * Both licenses apply only to original StormByte-System source in this
20 * repository. They do not cover other StormByte modules or any third-party
21 * material shipped with this repository (including everything under
22 * thirdparty/, and in particular the bundled StormByte Base tree), which
23 * remains under its own license.
24 *
25 * Neither license grants any patent rights. Any patent licenses required
26 * to use this software or third-party components must be obtained separately
27 * from the patent holders.
28 *
29 * StormByte-System is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU Lesser General Public License for more details.
33 *
34 * You should have received a copy of the GNU Lesser General Public License
35 * version 3 along with StormByte-System. If not, see
36 * <https://www.gnu.org/licenses/lgpl-3.0.html>.
37 *
38 * SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-StormByte-Commercial
39 */
40
41#pragma once
42
43#pragma once
44
45#include <StormByte/cstring.hxx>
46#include <StormByte/error.hxx>
49
50#include <chrono>
51#include <filesystem>
52#include <iostream>
53#include <memory>
54#include <string>
55#include <string_view>
56#include <system_error>
57#include <vector>
58#ifdef WINDOWS
59#include <windows.h>
60#else
61#include <unistd.h>
62#endif
63
64namespace StormByte::System {
65 class Pipe;
66 class ProcessImplementation;
67
72 struct {} typedef _EoF;
73
77 static constexpr const _EoF EoF = {};
78
92 public:
99 enum class Error {
100 Success = 0,
101 ExecutableNotFound,
102 CreationFailed,
103 Permission,
104 NotRunning,
105 AlreadyExited,
106 TimedOut,
107 BrokenPipe,
108 Canceled
109 };
110
115 enum class Status: unsigned short {
116 RUNNING,
117 SUSPENDED,
118 TERMINATED
119 };
120
126 Process(const std::filesystem::path& prog, const std::vector<StormByte::String::String>& args = {}) noexcept;
127
133 Process(std::filesystem::path&& prog, std::vector<StormByte::String::String>&& args = {}) noexcept;
134
135 Process(const Process& proc) = delete;
136
140 Process(Process&& proc) noexcept;
141
142 Process& operator=(const Process& proc) = delete;
143
147 Process& operator=(Process&& proc) noexcept;
148
152 virtual ~Process() noexcept;
153
158 explicit operator bool() const noexcept;
159
164 StormByte::Error::Fault Fault() const noexcept;
165
166 #ifdef UNIX
171 int Wait() noexcept;
172
178 int Wait(std::chrono::milliseconds timeout) noexcept;
179
184 pid_t Pid() noexcept;
185 #else
190 DWORD Wait() noexcept;
191
197 DWORD Wait(std::chrono::milliseconds timeout) noexcept;
198
203 PROCESS_INFORMATION Pid();
204 #endif
205
209 void Suspend();
210
214 void Resume();
215
222
229
236
243 STORMBYTE_FORCE_INLINE friend std::ostream& operator<<(std::ostream& ostream, const Process& proc) {
245 proc >> owned;
246 return ostream << static_cast<std::string>(owned);
247 }
248
254 Process& operator<<(std::string_view str);
255
262
269
274 void operator<<(const System::_EoF& eof);
275
276 private:
277 #ifdef WINDOWS
283 static std::string QuoteWindowsArgument(std::string_view argument);
284
289 std::wstring FullCommand() const;
290 #endif
291
296 void Send(std::string_view str);
297
301 void Run();
302
306 void ReleaseOwnership() noexcept;
307
311 void JoinForwarder() noexcept;
312
317 void StopForwarder(bool close_source_read) noexcept;
318
319 std::unique_ptr<ProcessImplementation> m_implementation;
320 };
321
322}
323
327template<>
328struct StormByte::Error::Domain<StormByte::System::Process::Error> {
329 static constexpr const char* Name = "StormByte.System.Process";
330
337 switch (e) {
339 return "Success";
341 return "Executable not found";
343 return "Process creation failed";
345 return "Process permission denied";
347 return "Process is not running";
349 return "Process has already exited";
351 return "Process wait timed out";
353 return "Process pipe is broken";
355 return "Process operation canceled";
356 }
357 return "Unknown Process error";
358 }
359};
360
361namespace StormByte::System {
367
373 STORMBYTE_SYSTEM_PUBLIC std::error_code make_error_code(Process::Error e) noexcept;
374}
375
376namespace std {
380 template<>
381 struct is_error_code_enum<StormByte::System::Process::Error>: true_type {};
382}
Runs an external program with piped stdin/stdout/stderr.
Definition process.hxx:91
Process & operator=(const Process &proc)=delete
void operator<<(const System::_EoF &eof)
Close process stdin (write end).
Process & operator=(Process &&proc) noexcept
Move assignment (invalidates the source).
STORMBYTE_FORCE_INLINE friend std::ostream & operator<<(std::ostream &ostream, const Process &proc)
Stream process stdout to an ostream.
Definition process.hxx:243
void Suspend()
Suspend the child process.
Process(std::filesystem::path &&prog, std::vector< StormByte::String::String > &&args={}) noexcept
Construct and start (moved).
Error
Child-process enumerators.
Definition process.hxx:99
@ Canceled
The operation was canceled.
@ ExecutableNotFound
The program path or name could not be resolved.
@ AlreadyExited
The child has already exited.
@ CreationFailed
The child could not be created (fork, pipe, CreateProcess)
@ TimedOut
A timed wait expired.
@ NotRunning
There is no live child for this operation.
@ Permission
The caller may not create or signal this child.
@ BrokenPipe
stdin/stdout/stderr pipe is closed or unusable
Process & operator<<(std::string_view str)
Write UTF-8 text to process stdin.
Process(const Process &proc)=delete
Process(Process &&proc) noexcept
Move constructor (invalidates the source).
void Resume()
Resume a suspended child process.
virtual ~Process() noexcept
Destructor (waits if still owning a child, then frees pipes).
Status
Process lifecycle.
Definition process.hxx:115
Process(const std::filesystem::path &prog, const std::vector< StormByte::String::String > &args={}) noexcept
Construct and start.
Process & operator<<(const StormByte::String::String &str)
Write owned UTF-8 text to process stdin.
Process & operator<<(const StormByte::CString &str)
Write a CString to process stdin.
StormByte::String::String & Stderr(StormByte::String::String &str) const
Read remaining stderr into owned text.
Process & operator>>(Process &proc)
Forward this process stdout to proc stdin (background thread).
StormByte::String::String & operator>>(StormByte::String::String &str) const
Read remaining stdout into owned text.
int Wait() noexcept
Block until the process exits (no timeout).
System module of the StormByte suite.
Definition device.hxx:58
static constexpr const _EoF EoF
Sentinel used as process << System::EoF to close stdin.
Definition process.hxx:77
const StormByte::Error::Category< Process::Error > & process_category() noexcept
Category singleton for Process::Error.
STL namespace.
#define STORMBYTE_FORCE_INLINE
static std::string Message(StormByte::System::Process::Error e)
Text for one Process enumerator.
Definition process.hxx:336
Tag type to close process stdin (write end).
Definition process.hxx:72
#define STORMBYTE_SYSTEM_PUBLIC
Definition visibility.h:53