process.cpp 3.7 KB

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