MinitScript  0.9.31 PRE-BETA
ApplicationMethods.cpp
Go to the documentation of this file.
1 #include <array>
2 #include <cstdio>
3 #include <cstdlib>
4 #include <span>
5 #include <memory>
6 
14 
15 using std::array;
16 using std::span;
17 using std::shared_ptr;
18 
20 
24 
27 
28 void ApplicationMethods::registerConstants(MinitScript* minitScript) {
29  minitScript->setConstant("$application::EXITCODE_SUCCESS", MinitScript::Variable(static_cast<int64_t>(EXIT_SUCCESS)));
30  minitScript->setConstant("$application::EXITCODE_FAILURE", MinitScript::Variable(static_cast<int64_t>(EXIT_FAILURE)));
31  //
32  #if defined(__FreeBSD__)
33  minitScript->setConstant("$application::OS", string("FreeBSD"));
34  #elif defined(__HAIKU__)
35  minitScript->setConstant("$application::OS", string("Haiku"));
36  #elif defined(__linux__)
37  minitScript->setConstant("$application::OS", string("Linux"));
38  #elif defined(__APPLE__)
39  minitScript->setConstant("$application::OS", string("MacOSX"));
40  #elif defined(__NetBSD__)
41  minitScript->setConstant("$application::OS", string("NetBSD"));
42  #elif defined(__OpenBSD__)
43  minitScript->setConstant("$application::OS", string("OpenBSD"));
44  #elif defined(_MSC_VER)
45  minitScript->setConstant("$application::OS", string("Windows-MSC"));
46  #elif defined(_WIN32)
47  minitScript->setConstant("$application::OS", string("Windows-MINGW"));
48  #else
49  minitScript->setConstant("$application::OS", string("Unknown"));
50  #endif
51  #if defined(__i386__) || defined(_M_IX86)
52  minitScript->setConstant("$application::CPU", string("X86"));
53  #elif defined(__amd64__) || defined(_M_X64)
54  minitScript->setConstant("$application::CPU", string("X64"));
55  #elif defined(__ia64__) || defined(_M_IA64)
56  minitScript->setConstant("$application::CPU", string("IA64"));
57  #elif defined(__aarch64__) || defined(_M_ARM64)
58  minitScript->setConstant("$application::CPU", string("ARM64"));
59  #elif defined(__arm__) || defined(_M_ARM)
60  minitScript->setConstant("$application::CPU", string("ARM"));
61  #elif defined(__riscv)
62  #if __riscv_xlen == 64
63  minitScript->setConstant("$application::CPU", string("RISCV64"));
64  #else
65  minitScript->setConstant("$application::CPU", string("RISCV"));
66  #endif
67  #elif defined(__powerpc64__)
68  minitScript->setConstant("$application::CPU", string("PPC64"));
69  #elif defined(__powerpc__)
70  minitScript->setConstant("$application::CPU", string("PPC"));
71  #else
72  minitScript->setConstant("$application::CPU", string("Unknown"));
73  #endif
74 }
75 
76 const string ApplicationMethods::execute(const string& command, int* exitCode, string* error) {
77  string result;
78  auto _command = command;
79  auto _exitCode = EXIT_FAILURE;
80  // error stream
81  string errorFile;
82  if (error != nullptr) {
83  errorFile = tmpnam(nullptr);
84  _command+= " 2>" + errorFile;
85  }
86  // execute command
87  FILE* pipe = nullptr;
88  try {
89  array<char, 128> buffer;
90  #if defined(_MSC_VER)
91  pipe = _popen(_command.c_str(), "r");
92  #else
93  pipe = popen(_command.c_str(), "r");
94  #endif
95  if (pipe == nullptr) throw std::runtime_error("popen() failed!");
96  while (feof(pipe) == false) {
97  if (fgets(buffer.data(), buffer.size(), pipe) != nullptr) result += buffer.data();
98  }
99  } catch (Exception& exception) {
100  _Console::printLine("ApplicationMethods::execute(): An error occurred: " + string(exception.what()));
101  }
102  // get exit code, if we have a pipe
103  if (pipe != nullptr) {
104  #if defined(_MSC_VER)
105  _exitCode = _pclose(pipe);
106  #else
107  _exitCode = pclose(pipe);
108  #endif
109  }
110  // store it to given exit code int pointer
111  if (exitCode != nullptr) *exitCode = _exitCode;
112  // store error to given string error pointer
113  if (error != nullptr) {
114  try {
115  *error = FileSystem::getContentAsString(
116  FileSystem::getPathName(errorFile),
117  FileSystem::getFileName(errorFile)
118  );
119  FileSystem::removeFile(
120  FileSystem::getPathName(errorFile),
121  FileSystem::getFileName(errorFile)
122  );
123  } catch (Exception& exception) {
124  _Console::printLine("ApplicationMethods::execute(): An error occurred: " + string(exception.what()));
125  }
126  }
127  // done
128  return result;
129 }
130 
131 void ApplicationMethods::registerMethods(MinitScript* minitScript) {
132  // application
133  {
134  //
135  class MethodApplicationExecute: public MinitScript::Method {
136  private:
137  MinitScript* minitScript { nullptr };
138  public:
139  MethodApplicationExecute(MinitScript* minitScript):
141  {
142  { .type = MinitScript::TYPE_STRING, .name = "command", .optional = false, .reference = false, .nullable = false },
143  { .type = MinitScript::TYPE_INTEGER, .name = "exitCode", .optional = true, .reference = true, .nullable = true },
144  { .type = MinitScript::TYPE_STRING, .name = "error", .optional = true, .reference = true, .nullable = true },
145  },
146  MinitScript::TYPE_STRING
147  ),
148  minitScript(minitScript) {}
149  const string getMethodName() override {
150  return "application.execute";
151  }
152  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
153  string command;
154  if ((arguments.size() == 1 || arguments.size() == 2 || arguments.size() == 3) &&
155  MinitScript::getStringValue(arguments, 0, command) == true) {
156  int exitCode = -1;
157  string error;
158  int* exitCodePtr = arguments.size() >= 2?&exitCode:nullptr;
159  string* errorPtr = arguments.size() >= 3?&error:nullptr;
160  returnValue.setValue(ApplicationMethods::execute(command, exitCodePtr, errorPtr));
161  if (exitCodePtr != nullptr) arguments[1].setValue(static_cast<int64_t>(exitCode));
162  if (errorPtr != nullptr) arguments[2].setValue(error);
163  } else {
164  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
165  }
166  }
167  };
168  minitScript->registerMethod(new MethodApplicationExecute(minitScript));
169  }
170  //
171  if (minitScript->getContext() != nullptr) {
172  //
173  {
174  //
175  class MethodApplicationGetArguments: public MinitScript::Method {
176  private:
177  MinitScript* minitScript { nullptr };
178  public:
179  MethodApplicationGetArguments(MinitScript* minitScript):
180  MinitScript::Method({}, MinitScript::TYPE_ARRAY),
181  minitScript(minitScript) {}
182  const string getMethodName() override {
183  return "application.getArguments";
184  }
185  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
186  if (arguments.size() == 0) {
187  returnValue.setType(MinitScript::TYPE_ARRAY);
188  for (const auto& argumentValue: minitScript->getContext()->getArgumentValues()) {
189  returnValue.pushArrayEntry(MinitScript::Variable(argumentValue));
190  }
191  } else {
192  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
193  }
194  }
195  };
196  minitScript->registerMethod(new MethodApplicationGetArguments(minitScript));
197  }
198  {
199  //
200  class MethodApplicationExit: public MinitScript::Method {
201  private:
202  MinitScript* minitScript { nullptr };
203  public:
204  MethodApplicationExit(MinitScript* minitScript):
206  {
207  { .type = MinitScript::TYPE_INTEGER, .name = "exitCode", .optional = true, .reference = false, .nullable = false },
208  }
209  ),
210  minitScript(minitScript) {}
211  const string getMethodName() override {
212  return "application.exit";
213  }
214  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
215  int64_t exitCode = 0ll;
216  if ((arguments.size() == 0 || arguments.size() == 1) &&
217  MinitScript::getIntegerValue(arguments, 0, exitCode, true) == true) {
218  minitScript->getContext()->setExitCode(static_cast<int>(exitCode));
219  minitScript->stopScriptExecution();
220  minitScript->stopRunning();
221  } else {
222  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
223  }
224  }
225  };
226  minitScript->registerMethod(new MethodApplicationExit(minitScript));
227  }
228  }
229 }
#define MINITSCRIPT_METHODUSAGE_COMPLAIN(methodName)
Definition: MinitScript.h:59
MinitScript script application methods.
const vector< string > & getArgumentValues()
Definition: Context.h:53
void setExitCode(int exitCode)
Set exit code.
Definition: Context.h:111
void pushArrayEntry(const Variable &value)
Push entry to array.
Definition: MinitScript.h:1892
void setType(VariableType newType)
Set type.
Definition: MinitScript.h:1253
void setValue(const Variable &variable)
Set value from given variable into variable.
Definition: MinitScript.h:1618
void registerMethod(Method *method)
Register method.
void stopScriptExecution()
Stop script execution.
Definition: MinitScript.h:3399
static void setConstant(Variable &variable)
Set variable recursively to be a constant.
Definition: MinitScript.h:4255
void stopRunning()
Set running flag to false.
Definition: MinitScript.h:3392
static void printLine()
Print newline to console.
Definition: Console.cpp:66
std::exception Exception
Exception base class.
Definition: Exception.h:18