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> 46 #include <semaphore.h> 48 #include <sys/select.h> 49 #include <sys/socket.h> 51 #include <sys/prctl.h> 58 mutex_ = CreateMutex(0,
FALSE, 0);
60 pthread_mutex_init(&mutex_,
nullptr);
68 pthread_mutex_destroy(&mutex_);
74 WaitForSingleObject(mutex_, INFINITE);
76 pthread_mutex_lock(&mutex_);
84 pthread_mutex_unlock(&mutex_);
91 LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE)func;
102 pthread_attr_init(&attr);
103 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
104 pthread_create(&helper, &attr, func, arg);
108 #ifndef GRAPHICS_DISABLED 117 pthread_exit(
nullptr);
124 proc.append(executable);
127 std::cout <<
"Starting " << proc << std::endl;
129 STARTUPINFO start_info;
130 PROCESS_INFORMATION proc_info;
131 GetStartupInfo(&start_info);
132 if (!CreateProcess(
nullptr, const_cast<char*>(proc.c_str()),
nullptr,
nullptr,
FALSE,
133 CREATE_NO_WINDOW | DETACHED_PROCESS,
nullptr,
nullptr,
134 &start_info, &proc_info))
143 prctl(PR_SET_PDEATHSIG, 2, 0, 0, 0);
145 char* mutable_args = strdup(args);
147 for (
int i = 0; mutable_args[i]; ++i) {
148 if (mutable_args[i] ==
' ') {
152 std::unique_ptr<char*[]> argv(
new char*[argc + 2]);
153 argv[0] = strdup(executable);
154 argv[1] = mutable_args;
156 bool inquote =
false;
157 for (
int i = 0; mutable_args[i]; ++i) {
158 if (!inquote && mutable_args[i] ==
' ') {
159 mutable_args[i] =
'\0';
160 argv[argc++] = mutable_args + i + 1;
161 }
else if (mutable_args[i] ==
'"') {
163 mutable_args[i] =
' ';
166 argv[argc] =
nullptr;
167 execvp(executable, argv.get());
176 semaphore_ = CreateSemaphore(0, 0, 10, 0);
177 #elif defined(__APPLE__) 179 snprintf(name,
sizeof(name),
"%ld", random());
181 semaphore_ = sem_open(name, O_CREAT , S_IWUSR, 0);
182 if (semaphore_ == SEM_FAILED) {
186 sem_init(&semaphore_, 0, 0);
192 CloseHandle(semaphore_);
193 #elif defined(__APPLE__) 194 sem_close(semaphore_);
196 sem_close(&semaphore_);
202 ReleaseSemaphore(semaphore_, 1,
nullptr);
203 #elif defined(__APPLE__) 204 sem_post(semaphore_);
206 sem_post(&semaphore_);
212 WaitForSingleObject(semaphore_, INFINITE);
213 #elif defined(__APPLE__) 214 sem_wait(semaphore_);
216 sem_wait(&semaphore_);
223 msg_buffer_out_.append(msg);
230 while (!msg_buffer_out_.empty()) {
231 int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
232 msg_buffer_out_.erase(0, i);
240 char* result =
nullptr;
241 #if defined(_WIN32) || defined(__CYGWIN__) 242 if (has_content) { result = strtok (
nullptr,
"\n"); }
244 if (buffer_ptr_ !=
nullptr) { result = strtok_r(
nullptr,
"\n", &buffer_ptr_); }
248 if (result !=
nullptr) {
return result;
251 buffer_ptr_ =
nullptr;
263 FD_SET(stream_, &readfds);
265 int i = select(stream_+1, &readfds,
nullptr,
nullptr, &tv);
268 if (i == 0) {
return nullptr; }
274 if (i <= 0) {
return nullptr; }
275 msg_buffer_in_[i] =
'\0';
278 return strtok(msg_buffer_in_,
"\n");
281 return strtok_r(msg_buffer_in_,
"\n", &buffer_ptr_);
289 closesocket(stream_);
299 static const char* ScrollViewProg() {
301 const char* prog =
"java -Xms512m -Xmx1024m";
303 const char* prog =
"sh";
310 static std::string ScrollViewCommand(std::string scrollview_path) {
317 const char cmd_template[] =
"-Djava.library.path=%s -jar %s/ScrollView.jar";
320 const char cmd_template[] =
321 "-c \"trap 'kill %%1' 0 1 2 ; java " 322 "-Xms1024m -Xmx2048m -jar %s/ScrollView.jar" 325 size_t cmdlen =
sizeof(cmd_template) + 2 * scrollview_path.size() + 1;
326 std::vector<char> cmd(cmdlen);
327 const char* sv_path = scrollview_path.c_str();
329 snprintf(&cmd[0], cmdlen, cmd_template, sv_path, sv_path);
331 snprintf(&cmd[0], cmdlen, cmd_template, sv_path);
333 std::string command(&cmd[0]);
340 msg_buffer_in_[0] =
'\0';
343 buffer_ptr_ =
nullptr;
345 struct addrinfo *addr_info =
nullptr;
347 snprintf(port_str, 40,
"%d", port);
351 int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
353 std::cerr <<
"WSAStartup failed: " << iResult << std::endl;
357 if (getaddrinfo(hostname, port_str,
nullptr, &addr_info) != 0) {
358 std::cerr <<
"Error resolving name for ScrollView host " 359 << std::string(hostname) <<
":" << port << std::endl;
365 stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
366 addr_info->ai_protocol);
369 std::cerr <<
"Failed to open socket" << std::endl;
370 }
else if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
372 const char* scrollview_path = getenv(
"SCROLLVIEW_PATH");
373 if (scrollview_path ==
nullptr) {
374 #ifdef SCROLLVIEW_PATH 376 #define _XSTR(a) _STR(a) 377 scrollview_path = _XSTR(SCROLLVIEW_PATH);
381 scrollview_path =
".";
384 const char *prog = ScrollViewProg();
385 std::string command = ScrollViewCommand(scrollview_path);
393 stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
394 addr_info->ai_protocol);
396 if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) == 0) {
402 std::cout <<
"ScrollView: Waiting for server...\n";
403 std::this_thread::sleep_for(std::chrono::seconds(1));
410 freeaddrinfo(addr_info);
415 delete[] msg_buffer_in_;
418 #endif // GRAPHICS_DISABLED void Lock()
Locks on a mutex.
void Unlock()
Unlocks on a mutex.
~SVMutex()
Destroys the mutex.
void Signal()
Signal a semaphore.
void Flush()
Flush the buffer.
static void StartThread(void *(*func)(void *), void *arg)
Create new thread.
SVSemaphore()
Sets up a semaphore.
static void StartProcess(const char *executable, const char *args)
Starts a new process.
void Wait()
Wait on a semaphore.
SVMutex()
Sets up a new mutex.
static void ExitThread()
Signals a thread to exit.
void Close()
Close the connection to the server.
~SVSemaphore()
Cleans up the mutex.
SVNetwork(const char *hostname, int port)
Set up a connection to hostname on port.
void Send(const char *msg)
Put a message in the messagebuffer to the server and try to send it.