Coverage Report

Created: 2026-08-14 20:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/util/subprocess.h
Line
Count
Source
1
// Based on the https://github.com/arun11299/cpp-subprocess project.
2
3
/*!
4
5
Documentation for C++ subprocessing library.
6
7
@copyright The code is licensed under the [MIT
8
  License](http://opensource.org/licenses/MIT):
9
  <br>
10
  Copyright &copy; 2016-2018 Arun Muralidharan.
11
  <br>
12
  Permission is hereby granted, free of charge, to any person obtaining a copy
13
  of this software and associated documentation files (the "Software"), to deal
14
  in the Software without restriction, including without limitation the rights
15
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
  copies of the Software, and to permit persons to whom the Software is
17
  furnished to do so, subject to the following conditions:
18
  <br>
19
  The above copyright notice and this permission notice shall be included in
20
  all copies or substantial portions of the Software.
21
  <br>
22
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
  SOFTWARE.
29
30
@author [Arun Muralidharan]
31
@see https://github.com/arun11299/cpp-subprocess to download the source code
32
33
@version 1.0.0
34
*/
35
36
#ifndef BITCOIN_UTIL_SUBPROCESS_H
37
#define BITCOIN_UTIL_SUBPROCESS_H
38
39
#include <util/check.h>
40
#include <util/syserror.h>
41
42
#include <algorithm>
43
#include <csignal>
44
#include <cstdio>
45
#include <cstdlib>
46
#include <cstring>
47
#include <exception>
48
#include <future>
49
#include <initializer_list>
50
#include <iostream>
51
#include <map>
52
#include <memory>
53
#include <sstream>
54
#include <string>
55
#include <vector>
56
57
extern "C" {
58
#ifdef WIN32
59
  #include <windows.h>
60
  #include <io.h>
61
#else
62
  #include <sys/wait.h>
63
  #include <unistd.h>
64
#endif
65
  #include <csignal>
66
  #include <fcntl.h>
67
  #include <sys/types.h>
68
}
69
70
// The Microsoft C++ compiler issues deprecation warnings
71
// for the standard POSIX function names.
72
// Its preferred implementations have a leading underscore.
73
// See: https://learn.microsoft.com/en-us/cpp/c-runtime-library/compatibility.
74
#if (defined _MSC_VER)
75
  #define subprocess_close _close
76
  #define subprocess_fileno _fileno
77
  #define subprocess_open _open
78
  #define subprocess_write _write
79
#else
80
166
  #define subprocess_close close
81
116
  #define subprocess_fileno fileno
82
  #define subprocess_open open
83
0
  #define subprocess_write write
84
#endif
85
86
/*!
87
 * Getting started with reading this source code.
88
 * The source is mainly divided into four parts:
89
 * 1. Exception Classes:
90
 *    These are very basic exception classes derived from
91
 *    runtime_error exception.
92
 *    There are two types of exception thrown from subprocess
93
 *    library: OSError and CalledProcessError
94
 *
95
 * 2. Popen Class
96
 *    This is the main class the users will deal with. It
97
 *    provides with all the API's to deal with processes.
98
 *
99
 * 3. Util namespace
100
 *    It includes some helper functions to split/join a string,
101
 *    reading from file descriptors, waiting on a process, fcntl
102
 *    options on file descriptors etc.
103
 *
104
 * 4. Detail namespace
105
 *    This includes some metaprogramming and helper classes.
106
 */
107
108
109
namespace subprocess {
110
111
// Max buffer size allocated on stack for read error
112
// from pipe
113
inline constexpr size_t SP_MAX_ERR_BUF_SIZ = 1024;
114
115
// Default buffer capacity for OutBuffer and ErrBuffer.
116
// If the data exceeds this capacity, the buffer size is grown
117
// by 1.5 times its previous capacity
118
inline constexpr size_t DEFAULT_BUF_CAP_BYTES = 8192;
119
120
121
/*-----------------------------------------------
122
 *    EXCEPTION CLASSES
123
 *-----------------------------------------------
124
 */
125
126
/*!
127
 * class: CalledProcessError
128
 * Thrown when there was error executing the command.
129
 * Check Popen class API's to know when this exception
130
 * can be thrown.
131
 *
132
 */
133
class CalledProcessError: public std::runtime_error
134
{
135
public:
136
  int retcode;
137
  CalledProcessError(const std::string& error_msg, int retcode):
138
2
    std::runtime_error(error_msg), retcode(retcode)
139
2
  {}
140
};
141
142
143
/*!
144
 * class: OSError
145
 * Thrown when some system call fails to execute or give result.
146
 * The exception message contains the name of the failed system call
147
 * with the stringisized errno code.
148
 * Check Popen class API's to know when this exception would be
149
 * thrown.
150
 * Its usual that the API exception specification would have
151
 * this exception together with CalledProcessError.
152
 */
153
class OSError: public std::runtime_error
154
{
155
public:
156
  OSError(const std::string& err_msg, int err_code):
157
0
    std::runtime_error(err_msg + ": " + SysErrorString(err_code))
158
0
  {}
159
};
160
161
//--------------------------------------------------------------------
162
namespace util
163
{
164
#ifdef WIN32
165
  inline void quote_argument(const std::string &argument, std::string &command_line,
166
                      bool force)
167
  {
168
    constexpr char quote = '"';
169
    constexpr char backslash = '\\';
170
171
    //
172
    // Unless we're told otherwise, don't quote unless we actually
173
    // need to do so --- hopefully avoid problems if programs won't
174
    // parse quotes properly
175
    //
176
177
    if (force == false && argument.empty() == false &&
178
        argument.find_first_of(" \t\n\v") == argument.npos) {
179
      command_line.append(argument);
180
    }
181
    else {
182
      command_line.push_back(quote);
183
184
      for (auto it = argument.begin();; ++it) {
185
        unsigned number_backslashes = 0;
186
187
        while (it != argument.end() && *it == backslash) {
188
          ++it;
189
          ++number_backslashes;
190
        }
191
192
        if (it == argument.end()) {
193
194
          //
195
          // Escape all backslashes, but let the terminating
196
          // double quotation mark we add below be interpreted
197
          // as a metacharacter.
198
          //
199
200
          command_line.append(number_backslashes * 2, backslash);
201
          break;
202
        }
203
        else if (*it == quote) {
204
205
          //
206
          // Escape all backslashes and the following
207
          // double quotation mark.
208
          //
209
210
          command_line.append(number_backslashes * 2 + 1, backslash);
211
          command_line.push_back(*it);
212
        }
213
        else {
214
215
          //
216
          // Backslashes aren't special here.
217
          //
218
219
          command_line.append(number_backslashes, backslash);
220
          command_line.push_back(*it);
221
        }
222
      }
223
224
      command_line.push_back(quote);
225
    }
226
  }
227
228
  inline std::string get_last_error(DWORD errorMessageID)
229
  {
230
    if (errorMessageID == 0)
231
      return std::string();
232
233
    LPSTR messageBuffer = nullptr;
234
    size_t size = FormatMessageA(
235
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
236
            FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
237
        NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
238
        (LPSTR)&messageBuffer, 0, NULL);
239
240
    std::string message(messageBuffer, size);
241
242
    LocalFree(messageBuffer);
243
244
    return message;
245
  }
246
247
  inline FILE *file_from_handle(HANDLE h, const char *mode)
248
  {
249
    int md;
250
    if (!mode) {
251
      throw OSError("invalid_mode", 0);
252
    }
253
254
    if (mode[0] == 'w') {
255
      md = _O_WRONLY;
256
    }
257
    else if (mode[0] == 'r') {
258
      md = _O_RDONLY;
259
    }
260
    else {
261
      throw OSError("file_from_handle", 0);
262
    }
263
264
    int os_fhandle = _open_osfhandle((intptr_t)h, md);
265
    if (os_fhandle == -1) {
266
      CloseHandle(h);
267
      throw OSError("_open_osfhandle", 0);
268
    }
269
270
    FILE *fp = _fdopen(os_fhandle, mode);
271
    if (fp == 0) {
272
      subprocess_close(os_fhandle);
273
      throw OSError("_fdopen", 0);
274
    }
275
276
    return fp;
277
  }
278
279
  inline void configure_pipe(HANDLE* read_handle, HANDLE* write_handle, HANDLE* child_handle)
280
  {
281
    SECURITY_ATTRIBUTES saAttr;
282
283
    // Set the bInheritHandle flag so pipe handles are inherited.
284
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
285
    saAttr.bInheritHandle = TRUE;
286
    saAttr.lpSecurityDescriptor = NULL;
287
288
    // Create a pipe for the child process's STDIN.
289
    if (!CreatePipe(read_handle, write_handle, &saAttr,0))
290
      throw OSError("CreatePipe", 0);
291
292
    // Ensure the write handle to the pipe for STDIN is not inherited.
293
    if (!SetHandleInformation(*child_handle, HANDLE_FLAG_INHERIT, 0))
294
      throw OSError("SetHandleInformation", 0);
295
  }
296
#endif
297
298
  /*!
299
   * Function: split
300
   * Parameters:
301
   * [in] str : Input string which needs to be split based upon the
302
   *            delimiters provided.
303
   * [in] deleims : Delimiter characters based upon which the string needs
304
   *                to be split. Default constructed to ' '(space) and '\t'(tab)
305
   * [out] vector<string> : Vector of strings split at deleimiter.
306
   */
307
  static inline std::vector<std::string>
308
  split(const std::string& str, const std::string& delims=" \t")
309
39
  {
310
39
    std::vector<std::string> res;
311
39
    size_t init = 0;
312
313
77
    while (true) {
314
77
      auto pos = str.find_first_of(delims, init);
315
77
      if (pos == std::string::npos) {
316
39
        res.emplace_back(str.substr(init, str.length()));
317
39
        break;
318
39
      }
319
38
      res.emplace_back(str.substr(init, pos - init));
320
38
      pos++;
321
38
      init = pos;
322
38
    }
323
324
39
    return res;
325
39
  }
Unexecuted instantiation: system_tests.cpp:subprocess::util::split(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
Unexecuted instantiation: run_command.cpp:subprocess::util::split(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
external_signer.cpp:subprocess::util::split(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
Line
Count
Source
309
39
  {
310
39
    std::vector<std::string> res;
311
39
    size_t init = 0;
312
313
77
    while (true) {
314
77
      auto pos = str.find_first_of(delims, init);
315
77
      if (pos == std::string::npos) {
316
39
        res.emplace_back(str.substr(init, str.length()));
317
39
        break;
318
39
      }
319
38
      res.emplace_back(str.substr(init, pos - init));
320
38
      pos++;
321
38
      init = pos;
322
38
    }
323
324
39
    return res;
325
39
  }
326
327
328
#ifndef WIN32
329
  /*!
330
   * Function: set_clo_on_exec
331
   * Sets/Resets the FD_CLOEXEC flag on the provided file descriptor
332
   * based upon the `set` parameter.
333
   * Parameters:
334
   * [in] fd : The descriptor on which FD_CLOEXEC needs to be set/reset.
335
   * [in] set : If 'true', set FD_CLOEXEC.
336
   *            If 'false' unset FD_CLOEXEC.
337
   */
338
  static inline
339
  void set_clo_on_exec(int fd, bool set = true)
340
320
  {
341
320
    int flags = fcntl(fd, F_GETFD, 0);
342
320
    if (flags == -1) {
343
0
        throw OSError("fcntl F_GETFD failed", errno);
344
0
    }
345
320
    if (set) flags |= FD_CLOEXEC;
346
0
    else flags &= ~FD_CLOEXEC;
347
320
    if (fcntl(fd, F_SETFD, flags) == -1) {
348
0
        throw OSError("fcntl F_SETFD failed", errno);
349
0
    }
350
320
  }
Unexecuted instantiation: system_tests.cpp:subprocess::util::set_clo_on_exec(int, bool)
run_command.cpp:subprocess::util::set_clo_on_exec(int, bool)
Line
Count
Source
340
320
  {
341
320
    int flags = fcntl(fd, F_GETFD, 0);
342
320
    if (flags == -1) {
343
0
        throw OSError("fcntl F_GETFD failed", errno);
344
0
    }
345
320
    if (set) flags |= FD_CLOEXEC;
346
0
    else flags &= ~FD_CLOEXEC;
347
320
    if (fcntl(fd, F_SETFD, flags) == -1) {
348
        throw OSError("fcntl F_SETFD failed", errno);
349
0
    }
350
320
  }
Unexecuted instantiation: external_signer.cpp:subprocess::util::set_clo_on_exec(int, bool)
351
352
353
  /*!
354
   * Function: pipe_cloexec
355
   * Creates a pipe and sets FD_CLOEXEC flag on both
356
   * read and write descriptors of the pipe.
357
   * Parameters:
358
   * [out] : A pair of file descriptors.
359
   *         First element of pair is the read descriptor of pipe.
360
   *         Second element is the write descriptor of pipe.
361
   */
362
  static inline
363
  std::pair<int, int> pipe_cloexec() noexcept(false)
364
160
  {
365
160
    int pipe_fds[2];
366
160
    int res = pipe(pipe_fds);
367
160
    if (res) {
368
0
      throw OSError("pipe failure", errno);
369
0
    }
370
371
160
    set_clo_on_exec(pipe_fds[0]);
372
160
    set_clo_on_exec(pipe_fds[1]);
373
374
160
    return std::make_pair(pipe_fds[0], pipe_fds[1]);
375
160
  }
Unexecuted instantiation: system_tests.cpp:subprocess::util::pipe_cloexec()
run_command.cpp:subprocess::util::pipe_cloexec()
Line
Count
Source
364
160
  {
365
160
    int pipe_fds[2];
366
160
    int res = pipe(pipe_fds);
367
160
    if (res) {
368
0
      throw OSError("pipe failure", errno);
369
0
    }
370
371
160
    set_clo_on_exec(pipe_fds[0]);
372
160
    set_clo_on_exec(pipe_fds[1]);
373
374
160
    return std::make_pair(pipe_fds[0], pipe_fds[1]);
375
160
  }
Unexecuted instantiation: external_signer.cpp:subprocess::util::pipe_cloexec()
376
#endif
377
378
379
  /*!
380
   * Function: write_n
381
   * Writes `length` bytes to the file descriptor `fd`
382
   * from the buffer `buf`.
383
   * Parameters:
384
   * [in] fd : The file descriptotr to write to.
385
   * [in] buf: Buffer from which data needs to be written to fd.
386
   * [in] length: The number of bytes that needs to be written from
387
   *              `buf` to `fd`.
388
   * [out] int : Number of bytes written or -1 in case of failure.
389
   */
390
  static inline
391
  int write_n(int fd, const char* buf, size_t length)
392
0
  {
393
0
    size_t nwritten = 0;
394
0
    while (nwritten < length) {
395
0
      int written = subprocess_write(fd, buf + nwritten, length - nwritten);
396
0
      if (written == -1) return -1;
397
0
      nwritten += written;
398
0
    }
399
0
    return nwritten;
400
0
  }
Unexecuted instantiation: system_tests.cpp:subprocess::util::write_n(int, char const*, unsigned long)
Unexecuted instantiation: run_command.cpp:subprocess::util::write_n(int, char const*, unsigned long)
Unexecuted instantiation: external_signer.cpp:subprocess::util::write_n(int, char const*, unsigned long)
401
402
403
  /*!
404
   * Function: read_atmost_n
405
   * Reads at the most `read_upto` bytes from the
406
   * file object `fp` before returning.
407
   * Parameters:
408
   * [in] fp : The file object from which it needs to read.
409
   * [in] buf : The buffer into which it needs to write the data.
410
   * [in] read_upto: Max number of bytes which must be read from `fd`.
411
   * [out] int : Number of bytes written to `buf` or read from `fd`
412
   *             OR -1 in case of error.
413
   *  NOTE: In case of EINTR while reading from socket, this API
414
   *  will retry to read from `fd`, but only till the EINTR counter
415
   *  reaches 50 after which it will return with whatever data it read.
416
   */
417
  static inline
418
  int read_atmost_n(FILE* fp, char* buf, size_t read_upto)
419
116
  {
420
#ifdef WIN32
421
    return (int)fread(buf, 1, read_upto, fp);
422
#else
423
116
    int fd = subprocess_fileno(fp);
424
116
    int rbytes = 0;
425
116
    int eintr_cnter = 0;
426
427
154
    while (1) {
428
154
      int read_bytes = read(fd, buf + rbytes, read_upto - rbytes);
429
154
      if (read_bytes == -1) {
430
0
        if (errno == EINTR) {
431
0
          if (eintr_cnter >= 50) return -1;
432
0
          eintr_cnter++;
433
0
          continue;
434
0
        }
435
0
        return -1;
436
0
      }
437
154
      if (read_bytes == 0) return rbytes;
438
439
38
      rbytes += read_bytes;
440
38
    }
441
0
    return rbytes;
442
116
#endif
443
116
  }
Unexecuted instantiation: system_tests.cpp:subprocess::util::read_atmost_n(_IO_FILE*, char*, unsigned long)
run_command.cpp:subprocess::util::read_atmost_n(_IO_FILE*, char*, unsigned long)
Line
Count
Source
419
116
  {
420
#ifdef WIN32
421
    return (int)fread(buf, 1, read_upto, fp);
422
#else
423
116
    int fd = subprocess_fileno(fp);
424
116
    int rbytes = 0;
425
116
    int eintr_cnter = 0;
426
427
154
    while (1) {
428
154
      int read_bytes = read(fd, buf + rbytes, read_upto - rbytes);
429
154
      if (read_bytes == -1) {
430
0
        if (errno == EINTR) {
431
0
          if (eintr_cnter >= 50) return -1;
432
0
          eintr_cnter++;
433
0
          continue;
434
0
        }
435
0
        return -1;
436
0
      }
437
154
      if (read_bytes == 0) return rbytes;
438
439
38
      rbytes += read_bytes;
440
38
    }
441
0
    return rbytes;
442
116
#endif
443
116
  }
Unexecuted instantiation: external_signer.cpp:subprocess::util::read_atmost_n(_IO_FILE*, char*, unsigned long)
444
445
446
  /*!
447
   * Function: read_all
448
   * Reads all the available data from `fp` into
449
   * `buf`. Internally calls read_atmost_n.
450
   * Parameters:
451
   * [in] fp : The file object from which to read from.
452
   * [in] buf : The buffer of type `class Buffer` into which
453
   *            the read data is written to.
454
   * [out] int: Number of bytes read OR -1 in case of failure.
455
   *
456
   * NOTE: `class Buffer` is a exposed public class. See below.
457
   */
458
459
  static inline int read_all(FILE* fp, std::vector<char>& buf)
460
76
  {
461
76
    auto buffer = buf.data();
462
76
    int total_bytes_read = 0;
463
76
    int fill_sz = buf.size();
464
465
76
    while (1) {
466
76
      const int rd_bytes = read_atmost_n(fp, buffer, fill_sz);
467
468
76
      if (rd_bytes == -1) { // Read finished
469
0
        if (total_bytes_read == 0) return -1;
470
0
        break;
471
472
76
      } else if (rd_bytes == fill_sz) { // Buffer full
473
0
        const auto orig_sz = buf.size();
474
0
        const auto new_sz = orig_sz * 2;
475
0
        buf.resize(new_sz);
476
0
        fill_sz = new_sz - orig_sz;
477
478
        //update the buffer pointer
479
0
        buffer = buf.data();
480
0
        total_bytes_read += rd_bytes;
481
0
        buffer += total_bytes_read;
482
483
76
      } else { // Partial data ? Continue reading
484
76
        total_bytes_read += rd_bytes;
485
76
        fill_sz -= rd_bytes;
486
76
        break;
487
76
      }
488
76
    }
489
76
    buf.erase(buf.begin()+total_bytes_read, buf.end()); // remove extra nulls
490
76
    return total_bytes_read;
491
76
  }
Unexecuted instantiation: system_tests.cpp:subprocess::util::read_all(_IO_FILE*, std::vector<char, std::allocator<char>>&)
run_command.cpp:subprocess::util::read_all(_IO_FILE*, std::vector<char, std::allocator<char>>&)
Line
Count
Source
460
76
  {
461
76
    auto buffer = buf.data();
462
76
    int total_bytes_read = 0;
463
76
    int fill_sz = buf.size();
464
465
76
    while (1) {
466
76
      const int rd_bytes = read_atmost_n(fp, buffer, fill_sz);
467
468
76
      if (rd_bytes == -1) { // Read finished
469
0
        if (total_bytes_read == 0) return -1;
470
0
        break;
471
472
76
      } else if (rd_bytes == fill_sz) { // Buffer full
473
0
        const auto orig_sz = buf.size();
474
0
        const auto new_sz = orig_sz * 2;
475
0
        buf.resize(new_sz);
476
0
        fill_sz = new_sz - orig_sz;
477
478
        //update the buffer pointer
479
0
        buffer = buf.data();
480
0
        total_bytes_read += rd_bytes;
481
0
        buffer += total_bytes_read;
482
483
76
      } else { // Partial data ? Continue reading
484
76
        total_bytes_read += rd_bytes;
485
76
        fill_sz -= rd_bytes;
486
76
        break;
487
76
      }
488
76
    }
489
76
    buf.erase(buf.begin()+total_bytes_read, buf.end()); // remove extra nulls
490
76
    return total_bytes_read;
491
76
  }
Unexecuted instantiation: external_signer.cpp:subprocess::util::read_all(_IO_FILE*, std::vector<char, std::allocator<char>>&)
492
493
#ifndef WIN32
494
  /*!
495
   * Function: wait_for_child_exit
496
   * Waits for the process with pid `pid` to exit
497
   * and returns its status.
498
   * Parameters:
499
   * [in] pid : The pid of the process.
500
   * [out] pair<int, int>:
501
   *    pair.first : Return code of the waitpid call.
502
   *    pair.second : Exit status of the process.
503
   *
504
   *  NOTE: This is a blocking call as in, it will loop
505
   *  till the child is exited.
506
   */
507
  static inline
508
  std::pair<int, int> wait_for_child_exit(int pid)
509
40
  {
510
40
    int status = 0;
511
40
    int ret = -1;
512
40
    while (1) {
513
40
      ret = waitpid(pid, &status, 0);
514
40
      if (ret == -1) break;
515
40
      if (ret == 0) continue;
516
40
      return std::make_pair(ret, status);
517
40
    }
518
519
0
    return std::make_pair(ret, status);
520
40
  }
Unexecuted instantiation: system_tests.cpp:subprocess::util::wait_for_child_exit(int)
run_command.cpp:subprocess::util::wait_for_child_exit(int)
Line
Count
Source
509
40
  {
510
40
    int status = 0;
511
40
    int ret = -1;
512
40
    while (1) {
513
40
      ret = waitpid(pid, &status, 0);
514
40
      if (ret == -1) break;
515
40
      if (ret == 0) continue;
516
40
      return std::make_pair(ret, status);
517
40
    }
518
519
0
    return std::make_pair(ret, status);
520
40
  }
Unexecuted instantiation: external_signer.cpp:subprocess::util::wait_for_child_exit(int)
521
#endif
522
523
} // end namespace util
524
525
526
527
/* -------------------------------
528
 *     Popen Arguments
529
 * -------------------------------
530
 */
531
532
/*!
533
 * Base class for all arguments involving string value.
534
 */
535
struct string_arg
536
{
537
0
  string_arg(const char* arg): arg_value(arg) {}
538
0
  string_arg(std::string&& arg): arg_value(std::move(arg)) {}
539
0
  string_arg(const std::string& arg): arg_value(arg) {}
540
  std::string arg_value;
541
};
542
543
/*!
544
 * Option to specify the executable name separately
545
 * from the args sequence.
546
 * In this case the cmd args must only contain the
547
 * options required for this executable.
548
 *
549
 * Eg: executable{"ls"}
550
 */
551
struct executable: string_arg
552
{
553
  template <typename T>
554
  executable(T&& arg): string_arg(std::forward<T>(arg)) {}
555
};
556
557
/*!
558
 * Used for redirecting input/output/error
559
 */
560
enum IOTYPE {
561
  STDOUT = 1,
562
  STDERR,
563
  PIPE,
564
};
565
566
//TODO: A common base/interface for below stream structures ??
567
568
/*!
569
 * Option to specify the input channel for the child
570
 * process. It can be:
571
 * 1. An already open file descriptor.
572
 * 2. A file name.
573
 * 3. IOTYPE. Usual a PIPE
574
 *
575
 * Eg: input{PIPE}
576
 * OR in case of redirection, output of another Popen
577
 * input{popen.output()}
578
 */
579
struct input
580
{
581
  // For an already existing file descriptor.
582
0
  explicit input(int fd): rd_ch_(fd) {}
583
584
  // FILE pointer.
585
0
  explicit input (FILE* fp):input(subprocess_fileno(fp)) { assert(fp); }
586
587
0
  explicit input(const char* filename) {
588
0
    int fd = subprocess_open(filename, O_RDONLY);
589
0
    if (fd == -1) throw OSError("File not found: ", errno);
590
0
    rd_ch_ = fd;
591
0
  }
592
40
  explicit input(IOTYPE typ) {
593
40
    assert (typ == PIPE && "STDOUT/STDERR not allowed");
594
40
#ifndef WIN32
595
40
    std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
596
40
#endif
597
40
  }
598
599
  int rd_ch_ = -1;
600
  int wr_ch_ = -1;
601
};
602
603
604
/*!
605
 * Option to specify the output channel for the child
606
 * process. It can be:
607
 * 1. An already open file descriptor.
608
 * 2. A file name.
609
 * 3. IOTYPE. Usually a PIPE.
610
 *
611
 * Eg: output{PIPE}
612
 * OR output{"output.txt"}
613
 */
614
struct output
615
{
616
0
  explicit output(int fd): wr_ch_(fd) {}
617
618
0
  explicit output (FILE* fp):output(subprocess_fileno(fp)) { assert(fp); }
619
620
0
  explicit output(const char* filename) {
621
0
    int fd = subprocess_open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
622
0
    if (fd == -1) throw OSError("File not found: ", errno);
623
0
    wr_ch_ = fd;
624
0
  }
625
40
  explicit output(IOTYPE typ) {
626
40
    assert (typ == PIPE && "STDOUT/STDERR not allowed");
627
40
#ifndef WIN32
628
40
    std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
629
40
#endif
630
40
  }
631
632
  int rd_ch_ = -1;
633
  int wr_ch_ = -1;
634
};
635
636
637
/*!
638
 * Option to specify the error channel for the child
639
 * process. It can be:
640
 * 1. An already open file descriptor.
641
 * 2. A file name.
642
 * 3. IOTYPE. Usually a PIPE or STDOUT
643
 *
644
 */
645
struct error
646
{
647
0
  explicit error(int fd): wr_ch_(fd) {}
648
649
0
  explicit error(FILE* fp):error(subprocess_fileno(fp)) { assert(fp); }
650
651
0
  explicit error(const char* filename) {
652
0
    int fd = subprocess_open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
653
0
    if (fd == -1) throw OSError("File not found: ", errno);
654
0
    wr_ch_ = fd;
655
0
  }
656
40
  explicit error(IOTYPE typ) {
657
40
    assert ((typ == PIPE || typ == STDOUT) && "STDERR not allowed");
658
40
    if (typ == PIPE) {
659
40
#ifndef WIN32
660
40
      std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
661
40
#endif
662
40
    } else {
663
      // Need to defer it till we have checked all arguments
664
0
      deferred_ = true;
665
0
    }
666
40
  }
667
668
  bool deferred_ = false;
669
  int rd_ch_ = -1;
670
  int wr_ch_ = -1;
671
};
672
673
// ~~~~ End Popen Args ~~~~
674
675
676
/*!
677
 * class: Buffer
678
 * This class is a very thin wrapper around std::vector<char>
679
 * This is basically used to determine the length of the actual
680
 * data stored inside the dynamically resized vector.
681
 *
682
 * This is what is returned as the output to the communicate
683
 * function, so, users must know about this class.
684
 *
685
 * OutBuffer and ErrBuffer are just different typedefs to this class.
686
 */
687
class Buffer
688
{
689
public:
690
76
  Buffer() = default;
691
0
  explicit Buffer(size_t cap) { buf.resize(cap); }
692
76
  void add_cap(size_t cap) { buf.resize(cap); }
693
694
public:
695
  std::vector<char> buf;
696
  size_t length = 0;
697
};
698
699
// Buffer for storing output written to output fd
700
using OutBuffer = Buffer;
701
// Buffer for storing output written to error fd
702
using ErrBuffer = Buffer;
703
704
705
// Fwd Decl.
706
class Popen;
707
708
/*---------------------------------------------------
709
 *      DETAIL NAMESPACE
710
 *---------------------------------------------------
711
 */
712
713
namespace detail {
714
/*!
715
 * A helper class to Popen class for setting
716
 * options as provided in the Popen constructor.
717
 * This design allows us to _not_ have any fixed position
718
 * to any arguments and specify them in a way similar to what
719
 * can be done in python.
720
 */
721
struct ArgumentDeducer
722
{
723
120
  ArgumentDeducer(Popen* p): popen_(p) {}
724
725
  void set_option(executable&& exe);
726
  void set_option(input&& inp);
727
  void set_option(output&& out);
728
  void set_option(error&& err);
729
730
private:
731
  Popen* popen_ = nullptr;
732
};
733
734
#ifndef WIN32
735
/*!
736
 * A helper class to Popen.
737
 * This takes care of all the fork-exec logic
738
 * in the execute_child API.
739
 */
740
class Child
741
{
742
public:
743
  Child(Popen* p, int err_wr_pipe):
744
0
    parent_(p),
745
0
    err_wr_pipe_(err_wr_pipe)
746
0
  {}
747
748
  void execute_child();
749
750
private:
751
  // Lets call it parent even though
752
  // technically a bit incorrect
753
  Popen* parent_ = nullptr;
754
  int err_wr_pipe_ = -1;
755
};
756
#endif
757
758
// Fwd Decl.
759
class Streams;
760
761
/*!
762
 * A helper class to Streams.
763
 * This takes care of management of communicating
764
 * with the child process with the means of the correct
765
 * file descriptor.
766
 */
767
class Communication
768
{
769
public:
770
40
  Communication(Streams* stream): stream_(stream)
771
40
  {}
772
  Communication(const Communication&) = delete;
773
  Communication& operator=(const Communication&) = delete;
774
  Communication(Communication&&) = default;
775
  Communication& operator=(Communication&&) = default;
776
public:
777
  int send(const char* msg, size_t length);
778
  int send(const std::vector<char>& msg);
779
780
  std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length);
781
  std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
782
0
  { return communicate(msg.data(), msg.size()); }
783
784
0
  void set_out_buf_cap(size_t cap) { out_buf_cap_ = cap; }
785
0
  void set_err_buf_cap(size_t cap) { err_buf_cap_ = cap; }
786
787
private:
788
  std::pair<OutBuffer, ErrBuffer> communicate_threaded(
789
      const char* msg, size_t length);
790
791
private:
792
  Streams* stream_;
793
  size_t out_buf_cap_ = DEFAULT_BUF_CAP_BYTES;
794
  size_t err_buf_cap_ = DEFAULT_BUF_CAP_BYTES;
795
};
796
797
798
799
/*!
800
 * This is a helper class to Popen.
801
 * It takes care of management of all the file descriptors
802
 * and file pointers.
803
 * It dispatches of the communication aspects to the
804
 * Communication class.
805
 * Read through the data members to understand about the
806
 * various file descriptors used.
807
 */
808
class Streams
809
{
810
public:
811
40
  Streams():comm_(this) {}
812
  Streams(const Streams&) = delete;
813
  Streams& operator=(const Streams&) = delete;
814
  Streams(Streams&&) = default;
815
  Streams& operator=(Streams&&) = default;
816
817
public:
818
  void setup_comm_channels();
819
820
  void cleanup_fds()
821
2
  {
822
2
    if (write_to_child_ != -1 && read_from_parent_ != -1) {
823
2
      subprocess_close(write_to_child_);
824
2
    }
825
2
    if (write_to_parent_ != -1 && read_from_child_ != -1) {
826
2
      subprocess_close(read_from_child_);
827
2
    }
828
2
    if (err_write_ != -1 && err_read_ != -1) {
829
2
      subprocess_close(err_read_);
830
2
    }
831
2
  }
832
833
  void close_parent_fds()
834
0
  {
835
0
    if (write_to_child_ != -1)  subprocess_close(write_to_child_);
836
0
    if (read_from_child_ != -1) subprocess_close(read_from_child_);
837
0
    if (err_read_ != -1)        subprocess_close(err_read_);
838
0
  }
839
840
  void close_child_fds()
841
40
  {
842
40
    if (write_to_parent_ != -1)  subprocess_close(write_to_parent_);
843
40
    if (read_from_parent_ != -1) subprocess_close(read_from_parent_);
844
40
    if (err_write_ != -1)        subprocess_close(err_write_);
845
40
  }
846
847
124
  FILE* input()  { return input_.get(); }
848
154
  FILE* output() { return output_.get(); }
849
154
  FILE* error()  { return error_.get(); }
850
851
40
  void input(FILE* fp)  { input_.reset(fp, fclose); }
852
40
  void output(FILE* fp) { output_.reset(fp, fclose); }
853
40
  void error(FILE* fp)  { error_.reset(fp, fclose); }
854
855
0
  void set_out_buf_cap(size_t cap) { comm_.set_out_buf_cap(cap); }
856
0
  void set_err_buf_cap(size_t cap) { comm_.set_err_buf_cap(cap); }
857
858
public: /* Communication forwarding API's */
859
  int send(const char* msg, size_t length)
860
4
  { return comm_.send(msg, length); }
861
862
  int send(const std::vector<char>& msg)
863
0
  { return comm_.send(msg); }
864
865
  std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
866
38
  { return comm_.communicate(msg, length); }
867
868
  std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
869
0
  { return comm_.communicate(msg); }
870
871
872
public:// Yes they are public
873
874
  std::shared_ptr<FILE> input_  = nullptr;
875
  std::shared_ptr<FILE> output_ = nullptr;
876
  std::shared_ptr<FILE> error_  = nullptr;
877
878
#ifdef WIN32
879
  HANDLE g_hChildStd_IN_Rd = nullptr;
880
  HANDLE g_hChildStd_IN_Wr = nullptr;
881
  HANDLE g_hChildStd_OUT_Rd = nullptr;
882
  HANDLE g_hChildStd_OUT_Wr = nullptr;
883
  HANDLE g_hChildStd_ERR_Rd = nullptr;
884
  HANDLE g_hChildStd_ERR_Wr = nullptr;
885
#endif
886
887
  // Pipes for communicating with child
888
889
  // Emulates stdin
890
  int write_to_child_   = -1; // Parent owned descriptor
891
  int read_from_parent_ = -1; // Child owned descriptor
892
893
  // Emulates stdout
894
  int write_to_parent_ = -1; // Child owned descriptor
895
  int read_from_child_ = -1; // Parent owned descriptor
896
897
  // Emulates stderr
898
  int err_write_ = -1; // Write error to parent (Child owned)
899
  int err_read_  = -1; // Read error from child (Parent owned)
900
901
private:
902
  Communication comm_;
903
};
904
905
} // end namespace detail
906
907
908
909
/*!
910
 * class: Popen
911
 * This is the single most important class in the whole library
912
 * and glues together all the helper classes to provide a common
913
 * interface to the client.
914
 *
915
 * API's provided by the class:
916
 * Popen({"cmd"}, output{..}, error{..}, ....)
917
 *    Command provided as a sequence.
918
 * wait()             - Wait for the child to exit.
919
 * retcode()          - The return code of the exited child.
920
 * send(...)          - Send input to the input channel of the child.
921
 * communicate(...)   - Get the output/error from the child and close the channels
922
 *                      from the parent side.
923
 */
924
class Popen
925
{
926
public:
927
  friend struct detail::ArgumentDeducer;
928
#ifndef WIN32
929
  friend class detail::Child;
930
#endif
931
932
  template <typename... Args>
933
  Popen(std::initializer_list<const char*> cmd_args, Args&& ...args)
934
  {
935
    vargs_.insert(vargs_.end(), cmd_args.begin(), cmd_args.end());
936
    init_args(std::forward<Args>(args)...);
937
938
    // Setup the communication channels of the Popen class
939
    stream_.setup_comm_channels();
940
941
    execute_process();
942
  }
943
944
  template <typename... Args>
945
40
  Popen(std::vector<std::string> vargs_, Args &&... args) : vargs_(vargs_)
946
40
  {
947
40
    init_args(std::forward<Args>(args)...);
948
949
    // Setup the communication channels of the Popen class
950
40
    stream_.setup_comm_channels();
951
952
40
    execute_process();
953
40
  }
954
955
38
  int retcode() const noexcept { return retcode_; }
956
957
  int wait() noexcept(false);
958
959
0
  void set_out_buf_cap(size_t cap) { stream_.set_out_buf_cap(cap); }
960
961
0
  void set_err_buf_cap(size_t cap) { stream_.set_err_buf_cap(cap); }
962
963
  int send(const char* msg, size_t length)
964
4
  { return stream_.send(msg, length); }
965
966
  int send(const std::string& msg)
967
4
  { return send(msg.c_str(), msg.size()); }
968
969
  int send(const std::vector<char>& msg)
970
0
  { return stream_.send(msg); }
971
972
  std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
973
38
  {
974
38
    auto res = stream_.communicate(msg, length);
975
38
    retcode_ = wait();
976
38
    return res;
977
38
  }
978
979
  std::pair<OutBuffer, ErrBuffer> communicate(const std::string& msg)
980
0
  {
981
0
    return communicate(msg.c_str(), msg.size());
982
0
  }
983
984
  std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
985
0
  {
986
0
    auto res = stream_.communicate(msg);
987
0
    retcode_ = wait();
988
0
    return res;
989
0
  }
990
991
  std::pair<OutBuffer, ErrBuffer> communicate()
992
38
  {
993
38
    return communicate(nullptr, 0);
994
38
  }
995
996
private:
997
  template <typename F, typename... Args>
998
  void init_args(F&& farg, Args&&... args);
999
  void init_args();
1000
  void populate_c_argv();
1001
  void execute_process() noexcept(false);
1002
1003
private:
1004
  detail::Streams stream_;
1005
1006
#ifdef WIN32
1007
  HANDLE process_handle_;
1008
  std::future<void> cleanup_future_;
1009
#else
1010
  // Pid of the child process
1011
  int child_pid_ = -1;
1012
#endif
1013
1014
  std::string exe_name_;
1015
1016
  // Command provided as sequence
1017
  std::vector<std::string> vargs_;
1018
  std::vector<char*> cargv_;
1019
1020
  int retcode_ = -1;
1021
};
1022
1023
40
inline void Popen::init_args() {
1024
40
  populate_c_argv();
1025
40
}
1026
1027
template <typename F, typename... Args>
1028
inline void Popen::init_args(F&& farg, Args&&... args)
1029
120
{
1030
120
  detail::ArgumentDeducer argd(this);
1031
120
  argd.set_option(std::forward<F>(farg));
1032
120
  init_args(std::forward<Args>(args)...);
1033
120
}
void subprocess::Popen::init_args<subprocess::input, subprocess::output, subprocess::error>(subprocess::input&&, subprocess::output&&, subprocess::error&&)
Line
Count
Source
1029
40
{
1030
40
  detail::ArgumentDeducer argd(this);
1031
40
  argd.set_option(std::forward<F>(farg));
1032
40
  init_args(std::forward<Args>(args)...);
1033
40
}
void subprocess::Popen::init_args<subprocess::output, subprocess::error>(subprocess::output&&, subprocess::error&&)
Line
Count
Source
1029
40
{
1030
40
  detail::ArgumentDeducer argd(this);
1031
40
  argd.set_option(std::forward<F>(farg));
1032
40
  init_args(std::forward<Args>(args)...);
1033
40
}
void subprocess::Popen::init_args<subprocess::error>(subprocess::error&&)
Line
Count
Source
1029
40
{
1030
40
  detail::ArgumentDeducer argd(this);
1031
40
  argd.set_option(std::forward<F>(farg));
1032
40
  init_args(std::forward<Args>(args)...);
1033
40
}
1034
1035
inline void Popen::populate_c_argv()
1036
40
{
1037
40
  cargv_.clear();
1038
40
  cargv_.reserve(vargs_.size() + 1);
1039
161
  for (auto& arg : vargs_) cargv_.push_back(&arg[0]);
1040
40
  cargv_.push_back(nullptr);
1041
40
}
1042
1043
inline int Popen::wait() noexcept(false)
1044
40
{
1045
#ifdef WIN32
1046
  int ret = WaitForSingleObject(process_handle_, INFINITE);
1047
1048
  // WaitForSingleObject with INFINITE should only return when process has signaled
1049
  if (ret != WAIT_OBJECT_0) {
1050
    throw OSError("Unexpected return code from WaitForSingleObject", 0);
1051
  }
1052
1053
  DWORD dretcode_;
1054
1055
  if (FALSE == GetExitCodeProcess(process_handle_, &dretcode_))
1056
      throw OSError("Failed during call to GetExitCodeProcess", 0);
1057
1058
  CloseHandle(process_handle_);
1059
1060
  return (int)dretcode_;
1061
#else
1062
40
  int ret, status;
1063
40
  std::tie(ret, status) = util::wait_for_child_exit(child_pid_);
1064
40
  if (ret == -1) {
1065
0
    if (errno != ECHILD) throw OSError("waitpid failed", errno);
1066
0
    return 0;
1067
0
  }
1068
40
  if (WIFEXITED(status)) return WEXITSTATUS(status);
1069
0
  if (WIFSIGNALED(status)) return WTERMSIG(status);
1070
0
  else return 255;
1071
1072
0
  return 0;
1073
0
#endif
1074
0
}
1075
1076
inline void Popen::execute_process() noexcept(false)
1077
40
{
1078
#ifdef WIN32
1079
  if (exe_name_.length()) {
1080
    this->vargs_.insert(this->vargs_.begin(), this->exe_name_);
1081
    this->populate_c_argv();
1082
  }
1083
  this->exe_name_ = vargs_[0];
1084
1085
  std::string argument;
1086
  std::string command_line;
1087
  bool first_arg = true;
1088
1089
  for (auto arg : this->vargs_) {
1090
    if (!first_arg) {
1091
      command_line += " ";
1092
    } else {
1093
      first_arg = false;
1094
    }
1095
    argument = arg;
1096
    util::quote_argument(argument, command_line, /*force=*/false);
1097
  }
1098
1099
  // CreateProcessA can modify szCmdLine so we allocate needed memory
1100
  char *szCmdline = new char[command_line.size() + 1];
1101
  strcpy_s(szCmdline, command_line.size() + 1, command_line.c_str());
1102
  PROCESS_INFORMATION piProcInfo;
1103
  STARTUPINFOA siStartInfo;
1104
  BOOL bSuccess = FALSE;
1105
  DWORD creation_flags = CREATE_NO_WINDOW;
1106
1107
  // Set up members of the PROCESS_INFORMATION structure.
1108
  ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
1109
1110
  // Set up members of the STARTUPINFOA structure.
1111
  // This structure specifies the STDIN and STDOUT handles for redirection.
1112
1113
  ZeroMemory(&siStartInfo, sizeof(STARTUPINFOA));
1114
  siStartInfo.cb = sizeof(STARTUPINFOA);
1115
1116
  siStartInfo.hStdError = this->stream_.g_hChildStd_ERR_Wr;
1117
  siStartInfo.hStdOutput = this->stream_.g_hChildStd_OUT_Wr;
1118
  siStartInfo.hStdInput = this->stream_.g_hChildStd_IN_Rd;
1119
1120
  siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
1121
1122
  // Create the child process.
1123
  bSuccess = CreateProcessA(NULL,
1124
                            szCmdline,    // command line
1125
                            NULL,         // process security attributes
1126
                            NULL,         // primary thread security attributes
1127
                            TRUE,         // handles are inherited
1128
                            creation_flags, // creation flags
1129
                            NULL,         // use parent's environment
1130
                            NULL,         // use parent's current directory
1131
                            &siStartInfo, // STARTUPINFOA pointer
1132
                            &piProcInfo); // receives PROCESS_INFORMATION
1133
1134
  // If an error occurs, exit the application.
1135
  if (!bSuccess) {
1136
    DWORD errorMessageID = ::GetLastError();
1137
    throw CalledProcessError("CreateProcess failed: " + util::get_last_error(errorMessageID), errorMessageID);
1138
  }
1139
1140
  CloseHandle(piProcInfo.hThread);
1141
1142
  /*
1143
    TODO: use common apis to close linux handles
1144
  */
1145
1146
  this->process_handle_ = piProcInfo.hProcess;
1147
1148
  this->cleanup_future_ = std::async(std::launch::async, [this] {
1149
    WaitForSingleObject(this->process_handle_, INFINITE);
1150
1151
    CloseHandle(this->stream_.g_hChildStd_ERR_Wr);
1152
    CloseHandle(this->stream_.g_hChildStd_OUT_Wr);
1153
    CloseHandle(this->stream_.g_hChildStd_IN_Rd);
1154
  });
1155
1156
/*
1157
  NOTE: In the linux version, there is a check to make sure that the process
1158
        has been started. Here, we do nothing because CreateProcess will throw
1159
        if we fail to create the process.
1160
*/
1161
1162
1163
#else
1164
1165
40
  int err_rd_pipe, err_wr_pipe;
1166
40
  std::tie(err_rd_pipe, err_wr_pipe) = util::pipe_cloexec();
1167
1168
40
  if (exe_name_.length()) {
1169
0
    vargs_.insert(vargs_.begin(), exe_name_);
1170
0
    populate_c_argv();
1171
0
  }
1172
40
  exe_name_ = vargs_[0];
1173
1174
40
  child_pid_ = fork();
1175
1176
40
  if (child_pid_ < 0) {
1177
0
    subprocess_close(err_rd_pipe);
1178
0
    subprocess_close(err_wr_pipe);
1179
0
    throw OSError("fork failed", errno);
1180
0
  }
1181
1182
40
  if (child_pid_ == 0)
1183
0
  {
1184
    // Close descriptors belonging to parent
1185
0
    stream_.close_parent_fds();
1186
1187
    //Close the read end of the error pipe
1188
0
    subprocess_close(err_rd_pipe);
1189
1190
0
    detail::Child chld(this, err_wr_pipe);
1191
0
    chld.execute_child();
1192
0
  }
1193
40
  else
1194
40
  {
1195
40
    subprocess_close(err_wr_pipe);// close child side of pipe, else get stuck in read below
1196
1197
40
    stream_.close_child_fds();
1198
1199
40
    try {
1200
40
      char err_buf[SP_MAX_ERR_BUF_SIZ] = {0,};
1201
1202
40
      FILE* err_fp = fdopen(err_rd_pipe, "r");
1203
40
      if (!err_fp) {
1204
0
          subprocess_close(err_rd_pipe);
1205
0
          throw OSError("fdopen failed", errno);
1206
0
      }
1207
40
      int read_bytes = util::read_atmost_n(err_fp, err_buf, SP_MAX_ERR_BUF_SIZ);
1208
40
      fclose(err_fp);
1209
1210
40
      if (read_bytes || strlen(err_buf)) {
1211
        // Call waitpid to reap the child process
1212
        // waitpid suspends the calling process until the
1213
        // child terminates.
1214
2
        int retcode = wait();
1215
1216
        // Throw whatever information we have about child failure
1217
2
        throw CalledProcessError(err_buf, retcode);
1218
2
      }
1219
40
    } catch (std::exception& exp) {
1220
2
      stream_.cleanup_fds();
1221
2
      throw;
1222
2
    }
1223
1224
40
  }
1225
40
#endif
1226
40
}
1227
1228
namespace detail {
1229
1230
0
  inline void ArgumentDeducer::set_option(executable&& exe) {
1231
0
    popen_->exe_name_ = std::move(exe.arg_value);
1232
0
  }
1233
1234
40
  inline void ArgumentDeducer::set_option(input&& inp) {
1235
40
    if (inp.rd_ch_ != -1) popen_->stream_.read_from_parent_ = inp.rd_ch_;
1236
40
    if (inp.wr_ch_ != -1) popen_->stream_.write_to_child_ = inp.wr_ch_;
1237
40
  }
1238
1239
40
  inline void ArgumentDeducer::set_option(output&& out) {
1240
40
    if (out.wr_ch_ != -1) popen_->stream_.write_to_parent_ = out.wr_ch_;
1241
40
    if (out.rd_ch_ != -1) popen_->stream_.read_from_child_ = out.rd_ch_;
1242
40
  }
1243
1244
40
  inline void ArgumentDeducer::set_option(error&& err) {
1245
40
    if (err.deferred_) {
1246
0
      if (popen_->stream_.write_to_parent_) {
1247
0
        popen_->stream_.err_write_ = popen_->stream_.write_to_parent_;
1248
0
      } else {
1249
0
        throw std::runtime_error("Set output before redirecting error to output");
1250
0
      }
1251
0
    }
1252
40
    if (err.wr_ch_ != -1) popen_->stream_.err_write_ = err.wr_ch_;
1253
40
    if (err.rd_ch_ != -1) popen_->stream_.err_read_ = err.rd_ch_;
1254
40
  }
1255
1256
1257
#ifndef WIN32
1258
0
  inline void Child::execute_child() {
1259
0
    int sys_ret = -1;
1260
0
    auto& stream = parent_->stream_;
1261
1262
0
    try {
1263
0
      if (stream.write_to_parent_ == 0)
1264
0
        stream.write_to_parent_ = dup(stream.write_to_parent_);
1265
1266
0
      if (stream.err_write_ == 0 || stream.err_write_ == 1)
1267
0
        stream.err_write_ = dup(stream.err_write_);
1268
1269
      // Make the child owned descriptors as the
1270
      // stdin, stdout and stderr for the child process
1271
0
      auto _dup2_ = [](int fd, int to_fd) {
1272
0
        if (fd == to_fd) {
1273
          // dup2 syscall does not reset the
1274
          // CLOEXEC flag if the descriptors
1275
          // provided to it are same.
1276
          // But, we need to reset the CLOEXEC
1277
          // flag as the provided descriptors
1278
          // are now going to be the standard
1279
          // input, output and error
1280
0
          util::set_clo_on_exec(fd, false);
1281
0
        } else if(fd != -1) {
1282
0
          int res = dup2(fd, to_fd);
1283
0
          if (res == -1) throw OSError("dup2 failed", errno);
1284
0
        }
1285
0
      };
1286
1287
      // Create the standard streams
1288
0
      _dup2_(stream.read_from_parent_, 0); // Input stream
1289
0
      _dup2_(stream.write_to_parent_,  1); // Output stream
1290
0
      _dup2_(stream.err_write_,        2); // Error stream
1291
1292
      // Close the duped descriptors
1293
0
      if (stream.read_from_parent_ != -1 && stream.read_from_parent_ > 2)
1294
0
        subprocess_close(stream.read_from_parent_);
1295
1296
0
      if (stream.write_to_parent_ != -1 && stream.write_to_parent_ > 2)
1297
0
        subprocess_close(stream.write_to_parent_);
1298
1299
0
      if (stream.err_write_ != -1 && stream.err_write_ > 2)
1300
0
        subprocess_close(stream.err_write_);
1301
1302
      // Replace the current image with the executable
1303
0
      sys_ret = execvp(parent_->exe_name_.c_str(), parent_->cargv_.data());
1304
1305
0
      if (sys_ret == -1) throw OSError("execve failed", errno);
1306
1307
0
    } catch (const OSError& exp) {
1308
      // Just write the exception message
1309
      // TODO: Give back stack trace ?
1310
0
      std::string err_msg(exp.what());
1311
      //ATTN: Can we do something on error here ?
1312
0
      util::write_n(err_wr_pipe_, err_msg.c_str(), err_msg.length());
1313
0
    }
1314
1315
    // Calling application would not get this
1316
    // exit failure
1317
0
    _exit (EXIT_FAILURE);
1318
0
  }
1319
#endif
1320
1321
1322
  inline void Streams::setup_comm_channels()
1323
40
  {
1324
#ifdef WIN32
1325
    util::configure_pipe(&this->g_hChildStd_IN_Rd, &this->g_hChildStd_IN_Wr, &this->g_hChildStd_IN_Wr);
1326
    this->input(util::file_from_handle(this->g_hChildStd_IN_Wr, "w"));
1327
    this->write_to_child_ = subprocess_fileno(this->input());
1328
1329
    util::configure_pipe(&this->g_hChildStd_OUT_Rd, &this->g_hChildStd_OUT_Wr, &this->g_hChildStd_OUT_Rd);
1330
    this->output(util::file_from_handle(this->g_hChildStd_OUT_Rd, "r"));
1331
    this->read_from_child_ = subprocess_fileno(this->output());
1332
1333
    util::configure_pipe(&this->g_hChildStd_ERR_Rd, &this->g_hChildStd_ERR_Wr, &this->g_hChildStd_ERR_Rd);
1334
    this->error(util::file_from_handle(this->g_hChildStd_ERR_Rd, "r"));
1335
    this->err_read_ = subprocess_fileno(this->error());
1336
#else
1337
1338
40
    if (write_to_child_ != -1)  input(fdopen(write_to_child_, "wb"));
1339
40
    if (read_from_child_ != -1) output(fdopen(read_from_child_, "rb"));
1340
40
    if (err_read_ != -1)        error(fdopen(err_read_, "rb"));
1341
1342
40
    auto handles = {input(), output(), error()};
1343
1344
120
    for (auto& h : handles) {
1345
120
      if (h == nullptr) continue;
1346
120
      setvbuf(h, nullptr, _IONBF, BUFSIZ);
1347
120
    }
1348
40
  #endif
1349
40
  }
1350
1351
  inline int Communication::send(const char* msg, size_t length)
1352
4
  {
1353
4
    if (stream_->input() == nullptr) return -1;
1354
4
    return std::fwrite(msg, sizeof(char), length, stream_->input());
1355
4
  }
1356
1357
  inline int Communication::send(const std::vector<char>& msg)
1358
0
  {
1359
0
    return send(msg.data(), msg.size());
1360
0
  }
1361
1362
  inline std::pair<OutBuffer, ErrBuffer>
1363
  Communication::communicate(const char* msg, size_t length)
1364
38
  {
1365
    // Optimization from subprocess.py
1366
    // If we are using one pipe, or no pipe
1367
    // at all, using select() or threads is unnecessary.
1368
38
    auto hndls = {stream_->input(), stream_->output(), stream_->error()};
1369
38
    int count = std::count(std::begin(hndls), std::end(hndls), nullptr);
1370
38
    const int len_conv = length;
1371
1372
38
    if (count >= 2) {
1373
0
      OutBuffer obuf;
1374
0
      ErrBuffer ebuf;
1375
0
      if (stream_->input()) {
1376
0
        if (msg) {
1377
0
          int wbytes = std::fwrite(msg, sizeof(char), length, stream_->input());
1378
0
          if (wbytes < len_conv) {
1379
0
            if (errno != EPIPE && errno != EINVAL) {
1380
0
              throw OSError("fwrite error", errno);
1381
0
            }
1382
0
          }
1383
0
        }
1384
        // Close the input stream
1385
0
        stream_->input_.reset();
1386
0
      } else if (stream_->output()) {
1387
        // Read till EOF
1388
        // ATTN: This could be blocking, if the process
1389
        // at the other end screws up, we get screwed as well
1390
0
        obuf.add_cap(out_buf_cap_);
1391
1392
0
        int rbytes = util::read_all(
1393
0
                            stream_->output(),
1394
0
                            obuf.buf);
1395
1396
0
        if (rbytes == -1) {
1397
0
          throw OSError("read to obuf failed", errno);
1398
0
        }
1399
1400
0
        obuf.length = rbytes;
1401
        // Close the output stream
1402
0
        stream_->output_.reset();
1403
1404
0
      } else if (stream_->error()) {
1405
        // Same screwness applies here as well
1406
0
        ebuf.add_cap(err_buf_cap_);
1407
1408
0
        int rbytes = util::read_atmost_n(
1409
0
                                  stream_->error(),
1410
0
                                  ebuf.buf.data(),
1411
0
                                  ebuf.buf.size());
1412
1413
0
        if (rbytes == -1) {
1414
0
          throw OSError("read to ebuf failed", errno);
1415
0
        }
1416
1417
0
        ebuf.length = rbytes;
1418
        // Close the error stream
1419
0
        stream_->error_.reset();
1420
0
      }
1421
0
      return std::make_pair(std::move(obuf), std::move(ebuf));
1422
0
    }
1423
1424
38
    return communicate_threaded(msg, length);
1425
38
  }
1426
1427
1428
  inline std::pair<OutBuffer, ErrBuffer>
1429
  Communication::communicate_threaded(const char* msg, size_t length)
1430
38
  {
1431
38
    OutBuffer obuf;
1432
38
    ErrBuffer ebuf;
1433
38
    std::future<int> out_fut, err_fut;
1434
38
    const int length_conv = length;
1435
1436
38
    if (stream_->output()) {
1437
38
      obuf.add_cap(out_buf_cap_);
1438
1439
38
      out_fut = std::async(std::launch::async,
1440
38
                          [&obuf, this] {
1441
38
                            return util::read_all(this->stream_->output(), obuf.buf);
1442
38
                          });
1443
38
    }
1444
38
    if (stream_->error()) {
1445
38
      ebuf.add_cap(err_buf_cap_);
1446
1447
38
      err_fut = std::async(std::launch::async,
1448
38
                          [&ebuf, this] {
1449
38
                            return util::read_all(this->stream_->error(), ebuf.buf);
1450
38
                          });
1451
38
    }
1452
38
    if (stream_->input()) {
1453
38
      if (msg) {
1454
0
        int wbytes = std::fwrite(msg, sizeof(char), length, stream_->input());
1455
0
        if (wbytes < length_conv) {
1456
0
          if (errno != EPIPE && errno != EINVAL) {
1457
0
            throw OSError("fwrite error", errno);
1458
0
          }
1459
0
        }
1460
0
      }
1461
38
      stream_->input_.reset();
1462
38
    }
1463
1464
38
    if (out_fut.valid()) {
1465
38
      int res = out_fut.get();
1466
38
      if (res != -1) obuf.length = res;
1467
0
      else obuf.length = 0;
1468
38
    }
1469
38
    if (err_fut.valid()) {
1470
38
      int res = err_fut.get();
1471
38
      if (res != -1) ebuf.length = res;
1472
0
      else ebuf.length = 0;
1473
38
    }
1474
1475
38
    return std::make_pair(std::move(obuf), std::move(ebuf));
1476
38
  }
1477
1478
} // end namespace detail
1479
1480
}
1481
1482
#endif // BITCOIN_UTIL_SUBPROCESS_H