#include "thread_util.h"
#include "program.h"
+#include <vector>
+#include <string.h>
+#include <stdio.h>
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
using namespace std;
* The child process closes unused sides of the pipe, and then calls exec to replace itself with the AI program
* The parent process closes unused sides of the pipe, and sets up member variables - associates streams with the pipe fd's for convenience.
*/
-Program::Program(const char * executablePath) : input(NULL), output(NULL), pid(0)
+Program::Program(const char * executablePath) : input(NULL), output(NULL), pid(0), paused(false)
{
+
+
+ /*
+ vector<char*> args;
+ if (executablePath[0] != '"')
+ args.push_back((char*)executablePath);
+ else
+ args.push_back((char*)(executablePath)+1);
+ char * token = NULL;
+ do
+ {
+ token = strstr(args[args.size()-1], " ");
+ if (token == NULL)
+ break;
+
+ *token = '\0';
+ do
+ {
+ ++token;
+ if (*token == '"')
+ *token = '\0';
+ }
+ while (*token != '\0' && iswspace(*token));
+
+ if (*token != '\0' && !iswspace(*token))
+ {
+ args.push_back(token);
+ }
+ else
+ break;
+ }
+ while (token != NULL);
+
+ char ** arguments = NULL;
+ if (args.size() > 0)
+ {
+ arguments = new char*[args.size()];
+ for (unsigned int i=0; i < args.size(); ++i)
+ arguments[i] = args[i];
+ }
+ */
//See if file exists and is executable...
if (access(executablePath, X_OK) != 0)
{
if (access(executablePath, X_OK) == 0) //Check we STILL have permissions to start the file
+ {
execl(executablePath, executablePath, (char*)(NULL)); ///Replace process with desired executable
-
+ //execv(executablePath,arguments); ///Replace process with desired executable
+ }
+ perror("execv error:\n");
fprintf(stderr, "Program::Program - Could not run program \"%s\"!\n", executablePath);
exit(EXIT_FAILURE); //We will probably have to terminate the whole program if this happens
}
}
+/**
+ * Forces the program to pause by sending SIGSTOP
+ * Program can be resumed by calling Continue() (which sends SIGCONT)
+ * @returns true if the program could be paused, false if it couldn't (probably because it wasn't running)
+ */
+bool Program::Pause()
+{
+ if (pid > 0 && kill(pid,SIGSTOP) == 0)
+ {
+ paused = true;
+ return true;
+ }
+ return false;
+}
+/**
+ * Causes a paused program to continue
+ * @returns true if the program could be continued, false if it couldn't (probably because it wasn't running)
+ */
+bool Program::Continue()
+{
+ if (pid > 0 && kill(pid,SIGCONT) == 0)
+ {
+ paused = false;
+ return true;
+ }
+ return false;
+}
+/**
+ * @returns true iff the program is paused
+ */
+bool Program::Paused() const
+{
+ return paused;
+}
/**
*/
bool Program::GetMessage(string & buffer, double timeout)
{
- if (!Running())
+ if (!Running() || timeout == 0)
return false;
+ struct timeval tv;
+ fd_set readfds;
+
+ tv.tv_sec = (int)(timeout);
+ tv.tv_usec = (timeout - (double)((int)timeout)) * 1000000;
+
+ int fd = fileno(input);
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ select(fd+1, &readfds, NULL, NULL, &tv);
+
+ if (!FD_ISSET(fd, &readfds))
+ return false; //Timed out
+ //fprintf(stderr, "Got message!\n");
+ for (char c = fgetc(input); c != '\n' && (int)(c) != EOF; c = fgetc(input))
+ {
+ //fprintf(stderr, "%c", c);
+ buffer += c;
+ }
+ //fprintf(stderr, "%s\n", buffer.c_str());
+ //fprintf(stderr,"DONE\n");
+ return true;
+
+ /* Old way, using threads, which apparently is terrible
assert(&buffer != NULL);
GetterThread getterThread(input, buffer);
assert(&(getterThread.buffer) != NULL);
+
TimerThread timerThread(timeout*1000000);
getterThread.Start();
}
getterThread.Stop();
- timerThread.Stop();
+ if (timeout > 0)
+ timerThread.Stop();
if (buffer.size() == 1 && buffer[0] == EOF)
return false;
return true;
-
+ */
}