24 # include "config_auto.h"
38 #pragma comment(lib, "Ws2_32.lib")
39 # include <winsock2.h>
40 # include <ws2tcpip.h>
42 #include <arpa/inet.h>
44 #include <netinet/in.h>
45 #include <semaphore.h>
47 #include <sys/select.h>
48 #include <sys/socket.h>
50 #include <sys/prctl.h>
55 #ifndef GRAPHICS_DISABLED
62 proc.append(executable);
65 std::cout <<
"Starting " << proc << std::endl;
67 STARTUPINFO start_info;
68 PROCESS_INFORMATION proc_info;
69 GetStartupInfo(&start_info);
70 if (!CreateProcess(
nullptr, const_cast<char*>(proc.c_str()),
nullptr,
nullptr,
FALSE,
71 CREATE_NO_WINDOW | DETACHED_PROCESS,
nullptr,
nullptr,
72 &start_info, &proc_info))
81 prctl(PR_SET_PDEATHSIG, 2, 0, 0, 0);
83 char* mutable_args = strdup(args);
85 for (
int i = 0; mutable_args[i]; ++i) {
86 if (mutable_args[i] ==
' ') {
90 std::unique_ptr<char*[]> argv(
new char*[argc + 2]);
91 argv[0] = strdup(executable);
92 argv[1] = mutable_args;
95 for (
int i = 0; mutable_args[i]; ++i) {
96 if (!inquote && mutable_args[i] ==
' ') {
97 mutable_args[i] =
'\0';
98 argv[argc++] = mutable_args + i + 1;
99 }
else if (mutable_args[i] ==
'"') {
101 mutable_args[i] =
' ';
104 argv[argc] =
nullptr;
105 execvp(executable, argv.get());
114 semaphore_ = CreateSemaphore(0, 0, 10, 0);
115 #elif defined(__APPLE__)
117 snprintf(name,
sizeof(name),
"%ld", random());
119 semaphore_ = sem_open(name, O_CREAT , S_IWUSR, 0);
120 if (semaphore_ == SEM_FAILED) {
124 sem_init(&semaphore_, 0, 0);
130 ReleaseSemaphore(semaphore_, 1,
nullptr);
131 #elif defined(__APPLE__)
132 sem_post(semaphore_);
134 sem_post(&semaphore_);
140 WaitForSingleObject(semaphore_, INFINITE);
141 #elif defined(__APPLE__)
142 sem_wait(semaphore_);
144 sem_wait(&semaphore_);
150 std::lock_guard<std::mutex> guard(mutex_send_);
151 msg_buffer_out_.append(msg);
156 std::lock_guard<std::mutex> guard(mutex_send_);
157 while (!msg_buffer_out_.empty()) {
158 int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
159 msg_buffer_out_.erase(0, i);
166 char* result =
nullptr;
167 #if defined(_WIN32) || defined(__CYGWIN__)
168 if (has_content) { result = strtok (
nullptr,
"\n"); }
170 if (buffer_ptr_ !=
nullptr) { result = strtok_r(
nullptr,
"\n", &buffer_ptr_); }
174 if (result !=
nullptr) {
return result;
177 buffer_ptr_ =
nullptr;
189 FD_SET(stream_, &readfds);
191 int i = select(stream_+1, &readfds,
nullptr,
nullptr, &tv);
194 if (i == 0) {
return nullptr; }
200 if (i <= 0) {
return nullptr; }
201 msg_buffer_in_[i] =
'\0';
204 return strtok(msg_buffer_in_,
"\n");
207 return strtok_r(msg_buffer_in_,
"\n", &buffer_ptr_);
215 closesocket(stream_);
225 static const char* ScrollViewProg() {
227 const char* prog =
"java -Xms512m -Xmx1024m";
229 const char* prog =
"sh";
243 const char cmd_template[] =
"-Djava.library.path=\"%s\" -jar \"%s/ScrollView.jar\"";
246 const char cmd_template[] =
247 "-c \"trap 'kill %%1' 0 1 2 ; java "
248 "-Xms1024m -Xmx2048m -jar %s/ScrollView.jar"
251 size_t cmdlen =
sizeof(cmd_template) + 2 * scrollview_path.size() + 1;
252 std::vector<char> cmd(cmdlen);
253 const char* sv_path = scrollview_path.c_str();
255 snprintf(&cmd[0], cmdlen, cmd_template, sv_path, sv_path);
257 snprintf(&cmd[0], cmdlen, cmd_template, sv_path);
266 msg_buffer_in_[0] =
'\0';
269 buffer_ptr_ =
nullptr;
271 struct addrinfo *addr_info =
nullptr;
273 snprintf(port_str, 40,
"%d", port);
277 int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
279 std::cerr <<
"WSAStartup failed: " << iResult << std::endl;
283 if (getaddrinfo(hostname, port_str,
nullptr, &addr_info) != 0) {
284 std::cerr <<
"Error resolving name for ScrollView host "
285 <<
std::string(hostname) <<
":" << port << std::endl;
291 stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
292 addr_info->ai_protocol);
295 std::cerr <<
"Failed to open socket" << std::endl;
296 }
else if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
298 const char* scrollview_path = getenv(
"SCROLLVIEW_PATH");
299 if (scrollview_path ==
nullptr) {
300 #ifdef SCROLLVIEW_PATH
302 #define _XSTR(a) _STR(a)
303 scrollview_path = _XSTR(SCROLLVIEW_PATH);
307 scrollview_path =
".";
310 const char *prog = ScrollViewProg();
311 std::string command = ScrollViewCommand(scrollview_path);
319 stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
320 addr_info->ai_protocol);
322 if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) == 0) {
328 std::cout <<
"ScrollView: Waiting for server...\n";
329 std::this_thread::sleep_for(std::chrono::seconds(1));
336 freeaddrinfo(addr_info);
341 delete[] msg_buffer_in_;
344 #endif // GRAPHICS_DISABLED