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