aboutsummaryrefslogtreecommitdiff
path: root/libbutl/command.mxx
blob: 8423f595d3c63caa4257b8f395c2e2ad490df4c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// file      : libbutl/command.mxx -*- C++ -*-
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef __cpp_modules_ts
#pragma once
#endif

#ifndef __cpp_lib_modules_ts
#include <map>
#include <string>
#include <cstddef>    // size_t
#include <functional>
#endif

// Other includes.

#ifdef __cpp_modules_ts
export module butl.command;
#ifdef __cpp_lib_modules_ts
import std.core;
#endif
import butl.process;
import butl.optional;
#else
#include <libbutl/process.mxx>
#include <libbutl/optional.mxx>
#endif

#include <libbutl/export.hxx>

LIBBUTL_MODEXPORT namespace butl
{
  // Run a process or a builtin, interpreting the command line as
  // whitespace-separated, potentially quoted program path/builtin name,
  // arguments, and redirects. Throw std::invalid_argument on the parsing
  // error, ios::failure on the underlying OS error, process_error on the
  // process running error and std::system_error on the builtin running error.
  //
  // To run a system utility rather than a builtin prefix its name with `^`,
  // for example:
  //
  // ^cat --squeeze-blank file
  //
  // The process environment path is unused and must point to the empty
  // process path.
  //
  // Currently only the following stdout redirects are supported:
  //
  // >file   # Overwrite file.
  // >>file  # Append to file.
  //
  // In particular, the file descriptor cannot be specified. The file path can
  // optionally be separated from '>' by whitespaces. Note that redirects are
  // distinguished from arguments by the presence of leading '>' and prior to
  // possible substitutions (so the redirect character cannot be the result of
  // a substitution; see below).
  //
  // The relative redirect file paths are completed against the command
  // current working directory. Note that if it is altered via the process
  // environment, then the new value is used.
  //
  // The command line elements (program, arguments, etc) may optionally
  // contain substitutions - variable names enclosed with the substitution
  // symbol ('@' by default) - which are replaced with the corresponding
  // variable values to produce the actual command. Variable names must not
  // contain whitespaces and an attempt to substitute an unknown or a
  // malformed variable is an error. Double substitution character ('@@' by
  // default) is an escape sequence.
  //
  // If the variable map is absent, then '@' has no special meaning and is
  // treated as a regular character.
  //
  // The callback function, if specified, is called prior to running the
  // command process with the substituted command elements and including
  // redirects which will be in the "canonical" form (single argument without
  // space after '>'). The callback can be used, for example, for tracing the
  // resulting command line, etc.
  //
  using command_substitution_map = std::map<std::string, std::string>;
  using command_callback = void (const char* const args[], std::size_t n);

  LIBBUTL_SYMEXPORT process_exit
  command_run (const std::string& command,
               const optional<process_env>& = nullopt,
               const optional<command_substitution_map>& = nullopt,
               char subst = '@',
               const std::function<command_callback>& = {});
}