24 # include "config_auto.h" 37 #pragma comment(lib, "Ws2_32.lib") 38 # include <winsock2.h> 39 # include <ws2tcpip.h> 41 #include <arpa/inet.h> 43 #include <netinet/in.h> 45 #include <semaphore.h> 47 #include <sys/select.h> 48 #include <sys/socket.h> 50 #include <sys/prctl.h> 57 mutex_ = CreateMutex(0,
FALSE, 0);
59 pthread_mutex_init(&mutex_,
nullptr);
65 WaitForSingleObject(mutex_, INFINITE);
67 pthread_mutex_lock(&mutex_);
75 pthread_mutex_unlock(&mutex_);
82 LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE)func;
93 pthread_attr_init(&attr);
94 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
95 pthread_create(&helper, &attr, func, arg);
99 #ifndef GRAPHICS_DISABLED 108 pthread_exit(
nullptr);
115 proc.append(executable);
118 std::cout <<
"Starting " << proc << std::endl;
120 STARTUPINFO start_info;
121 PROCESS_INFORMATION proc_info;
122 GetStartupInfo(&start_info);
123 if (!CreateProcess(
nullptr, const_cast<char*>(proc.c_str()),
nullptr,
nullptr,
FALSE,
124 CREATE_NO_WINDOW | DETACHED_PROCESS,
nullptr,
nullptr,
125 &start_info, &proc_info))
134 prctl(PR_SET_PDEATHSIG, 2, 0, 0, 0);
136 char* mutable_args = strdup(args);
138 for (
int i = 0; mutable_args[i]; ++i) {
139 if (mutable_args[i] ==
' ') {
143 std::unique_ptr<char*[]> argv(
new char*[argc + 2]);
144 argv[0] = strdup(executable);
145 argv[1] = mutable_args;
147 bool inquote =
false;
148 for (
int i = 0; mutable_args[i]; ++i) {
149 if (!inquote && mutable_args[i] ==
' ') {
150 mutable_args[i] =
'\0';
151 argv[argc++] = mutable_args + i + 1;
152 }
else if (mutable_args[i] ==
'"') {
154 mutable_args[i] =
' ';
157 argv[argc] =
nullptr;
158 execvp(executable, argv.get());
167 semaphore_ = CreateSemaphore(0, 0, 10, 0);
168 #elif defined(__APPLE__) 170 snprintf(name,
sizeof(name),
"%ld", random());
172 semaphore_ = sem_open(name, O_CREAT , S_IWUSR, 0);
173 if (semaphore_ == SEM_FAILED) {
177 sem_init(&semaphore_, 0, 0);
183 ReleaseSemaphore(semaphore_, 1,
nullptr);
184 #elif defined(__APPLE__) 185 sem_post(semaphore_);
187 sem_post(&semaphore_);
193 WaitForSingleObject(semaphore_, INFINITE);
194 #elif defined(__APPLE__) 195 sem_wait(semaphore_);
197 sem_wait(&semaphore_);
204 msg_buffer_out_.append(msg);
205 mutex_send_.Unlock();
211 while (!msg_buffer_out_.empty()) {
212 int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
213 msg_buffer_out_.erase(0, i);
215 mutex_send_.Unlock();
221 char* result =
nullptr;
222 #if defined(_WIN32) || defined(__CYGWIN__) 223 if (has_content) { result = strtok (
nullptr,
"\n"); }
225 if (buffer_ptr_ !=
nullptr) { result = strtok_r(
nullptr,
"\n", &buffer_ptr_); }
229 if (result !=
nullptr) {
return result;
232 buffer_ptr_ =
nullptr;
244 FD_SET(stream_, &readfds);
246 int i = select(stream_+1, &readfds,
nullptr,
nullptr, &tv);
249 if (i == 0) {
return nullptr; }
252 i = recv(stream_, msg_buffer_in_, kMaxMsgSize, 0);
255 if (i <= 0) {
return nullptr; }
256 msg_buffer_in_[i] =
'\0';
259 return strtok(msg_buffer_in_,
"\n");
262 return strtok_r(msg_buffer_in_,
"\n", &buffer_ptr_);
270 closesocket(stream_);
280 static const char* ScrollViewProg() {
282 const char* prog =
"java -Xms512m -Xmx1024m";
284 const char* prog =
"sh";
291 static std::string ScrollViewCommand(std::string scrollview_path) {
298 const char cmd_template[] =
"-Djava.library.path=%s -jar %s/ScrollView.jar";
301 const char cmd_template[] =
302 "-c \"trap 'kill %%1' 0 1 2 ; java " 303 "-Xms1024m -Xmx2048m -jar %s/ScrollView.jar" 306 size_t cmdlen =
sizeof(cmd_template) + 2 * scrollview_path.size() + 1;
307 std::vector<char> cmd(cmdlen);
308 const char* sv_path = scrollview_path.c_str();
310 snprintf(&cmd[0], cmdlen, cmd_template, sv_path, sv_path);
312 snprintf(&cmd[0], cmdlen, cmd_template, sv_path);
314 std::string command(&cmd[0]);
320 msg_buffer_in_ =
new char[kMaxMsgSize + 1];
321 msg_buffer_in_[0] =
'\0';
324 buffer_ptr_ =
nullptr;
326 struct addrinfo *addr_info =
nullptr;
328 snprintf(port_str, 40,
"%d", port);
332 int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
334 std::cerr <<
"WSAStartup failed: " << iResult << std::endl;
338 if (getaddrinfo(hostname, port_str,
nullptr, &addr_info) != 0) {
339 std::cerr <<
"Error resolving name for ScrollView host " 340 << std::string(hostname) <<
":" << port << std::endl;
346 stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
347 addr_info->ai_protocol);
350 std::cerr <<
"Failed to open socket" << std::endl;
351 }
else if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
353 const char* scrollview_path = getenv(
"SCROLLVIEW_PATH");
354 if (scrollview_path ==
nullptr) {
355 #ifdef SCROLLVIEW_PATH 357 #define _XSTR(a) _STR(a) 358 scrollview_path = _XSTR(SCROLLVIEW_PATH);
362 scrollview_path =
".";
365 const char *prog = ScrollViewProg();
366 std::string command = ScrollViewCommand(scrollview_path);
374 stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
375 addr_info->ai_protocol);
377 if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) == 0) {
383 std::cout <<
"ScrollView: Waiting for server...\n";
395 freeaddrinfo(addr_info);
400 delete[] msg_buffer_in_;
403 #endif // GRAPHICS_DISABLED void Signal()
Signal a semaphore.
void Close()
Close the connection to the server.
SVSemaphore()
Sets up a semaphore.
void Lock()
Locks on a mutex.
SVNetwork(const char *hostname, int port)
Set up a connection to hostname on port.
static void StartThread(void *(*func)(void *), void *arg)
Create new thread.
SVMutex()
Sets up a new mutex.
void Wait()
Wait on a semaphore.
void Send(const char *msg)
Put a message in the messagebuffer to the server and try to send it.
void Flush()
Flush the buffer.
static void ExitThread()
Signals a thread to exit.
void Unlock()
Unlocks on a mutex.
static void StartProcess(const char *executable, const char *args)
Starts a new process.