process.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright 2010-2020 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
  4. */
  5. #include "bx_p.h"
  6. #include <bx/process.h>
  7. #include <stdio.h>
  8. #ifndef BX_CONFIG_CRT_PROCESS
  9. # define BX_CONFIG_CRT_PROCESS !(0 \
  10. || BX_CRT_NONE \
  11. || BX_PLATFORM_EMSCRIPTEN \
  12. || BX_PLATFORM_PS4 \
  13. || BX_PLATFORM_WINRT \
  14. || BX_PLATFORM_XBOXONE \
  15. )
  16. #endif // BX_CONFIG_CRT_PROCESS
  17. namespace bx
  18. {
  19. #if BX_CONFIG_CRT_PROCESS
  20. #if BX_CRT_MSVC
  21. # define popen _popen
  22. # define pclose _pclose
  23. #endif // BX_CRT_MSVC
  24. ProcessReader::ProcessReader()
  25. : m_file(NULL)
  26. {
  27. }
  28. ProcessReader::~ProcessReader()
  29. {
  30. BX_ASSERT(NULL == m_file, "Process not closed!");
  31. }
  32. bool ProcessReader::open(const FilePath& _filePath, const StringView& _args, Error* _err)
  33. {
  34. BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
  35. if (NULL != m_file)
  36. {
  37. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessReader: File is already open.");
  38. return false;
  39. }
  40. char tmp[kMaxFilePath*2] = "\"";
  41. strCat(tmp, BX_COUNTOF(tmp), _filePath);
  42. strCat(tmp, BX_COUNTOF(tmp), "\" ");
  43. strCat(tmp, BX_COUNTOF(tmp), _args);
  44. m_file = popen(tmp, "r");
  45. if (NULL == m_file)
  46. {
  47. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessReader: Failed to open process.");
  48. return false;
  49. }
  50. return true;
  51. }
  52. void ProcessReader::close()
  53. {
  54. BX_ASSERT(NULL != m_file, "Process not open!");
  55. FILE* file = (FILE*)m_file;
  56. m_exitCode = pclose(file);
  57. m_file = NULL;
  58. }
  59. int32_t ProcessReader::read(void* _data, int32_t _size, Error* _err)
  60. {
  61. BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err);
  62. FILE* file = (FILE*)m_file;
  63. int32_t size = (int32_t)fread(_data, 1, _size, file);
  64. if (size != _size)
  65. {
  66. if (0 != feof(file) )
  67. {
  68. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "ProcessReader: EOF.");
  69. }
  70. else if (0 != ferror(file) )
  71. {
  72. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "ProcessReader: read error.");
  73. }
  74. return size >= 0 ? size : 0;
  75. }
  76. return size;
  77. }
  78. int32_t ProcessReader::getExitCode() const
  79. {
  80. return m_exitCode;
  81. }
  82. ProcessWriter::ProcessWriter()
  83. : m_file(NULL)
  84. {
  85. }
  86. ProcessWriter::~ProcessWriter()
  87. {
  88. BX_ASSERT(NULL == m_file, "Process not closed!");
  89. }
  90. bool ProcessWriter::open(const FilePath& _filePath, const StringView& _args, Error* _err)
  91. {
  92. BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
  93. if (NULL != m_file)
  94. {
  95. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessWriter: File is already open.");
  96. return false;
  97. }
  98. char tmp[kMaxFilePath*2] = "\"";
  99. strCat(tmp, BX_COUNTOF(tmp), _filePath);
  100. strCat(tmp, BX_COUNTOF(tmp), "\" ");
  101. strCat(tmp, BX_COUNTOF(tmp), _args);
  102. m_file = popen(tmp, "w");
  103. if (NULL == m_file)
  104. {
  105. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessWriter: Failed to open process.");
  106. return false;
  107. }
  108. return true;
  109. }
  110. void ProcessWriter::close()
  111. {
  112. BX_ASSERT(NULL != m_file, "Process not open!");
  113. FILE* file = (FILE*)m_file;
  114. m_exitCode = pclose(file);
  115. m_file = NULL;
  116. }
  117. int32_t ProcessWriter::write(const void* _data, int32_t _size, Error* _err)
  118. {
  119. BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err);
  120. FILE* file = (FILE*)m_file;
  121. int32_t size = (int32_t)fwrite(_data, 1, _size, file);
  122. if (size != _size)
  123. {
  124. if (0 != ferror(file) )
  125. {
  126. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "ProcessWriter: write error.");
  127. }
  128. return size >= 0 ? size : 0;
  129. }
  130. return size;
  131. }
  132. int32_t ProcessWriter::getExitCode() const
  133. {
  134. return m_exitCode;
  135. }
  136. #endif // BX_CONFIG_CRT_PROCESS
  137. } // namespace bx