diff --git a/.monadid b/.monadid
index 41492f066ad069d49dd2c8fc21987dc78f3aa429..33d5feb7e57d186ba5814eb41d32d4d23015e104 100644
--- a/.monadid
+++ b/.monadid
@@ -1,4 +1,4 @@
 monad identification file
 This file is used for monad directory identification
 Built by toole1 on linux1.ews.illinois.edu
-Build Date: Mon Jan 23 00:57:08 CST 2012
+Build Date: Tue Jan 24 17:14:38 CST 2012
diff --git a/Makefile b/Makefile
index 73b7aa492c4b3729e4e965ee795d6d67c5375fc0..8262302865c3d4b6e170666ae369c5bb3083179c 100644
--- a/Makefile
+++ b/Makefile
@@ -16,11 +16,14 @@ $(warning Invalid value specified for OPTIMIZE. Should be on or off)
 CFLAGS += -g -O0
 endif
 
-IS_LIBRT:=$(shell locate -l 1 -c librt.so)
+LIBS:=
+IS_LIBRT:=$(shell echo "int main(){}" | g++ -o /dev/null -x c++ - -lrt &>/dev/null ; echo $$?)
+IS_LIBPNG:=$(shell echo "int main(){}" | g++ -o /dev/null -x c++ - -lpng &>/dev/null ; echo $$?)
 ifeq ($(IS_LIBRT),0)
-LIBRT=
-else
-LIBRT=-lrt
+LIBS+= -lrt
+endif
+ifeq ($(IS_LIBPNG),0)
+LIBS+= -lpng 
 endif
 
 all: $(EXENAME) $(CCMONAD) $(IDFILE)
@@ -32,10 +35,10 @@ $(IDFILE): $(OBJS)
 'Build Date:' `date`> $(IDFILE)
 
 $(EXENAME): $(OBJS) $(IDFILE)
-	$(CC) $(CFLAGS) $(LIBRT) $(OBJS) -o $@
+	$(CC) $(CFLAGS) $(LIBS) $(OBJS) -o $@
 
 $(CCMONAD): $(CCOBJS) $(IDFILE)
-	$(CC) $(CFLAGS) $(LIBRT) $(CCOBJS) -o $@
+	$(CC) $(CFLAGS) $(LIBS) $(CCOBJS) -o $@
 
 help.o: help.cpp $(wildcard *.h) README.cgo README_config.cgo README_tests.cgo LICENSE.cgo quotes.cga
 
diff --git a/ccmonad b/ccmonad
index 0c9b9a7ef64a12268e50c5226fc826fbb0049e32..826a50bc4e32599060921c8261714a6901aa4858 100755
Binary files a/ccmonad and b/ccmonad differ
diff --git a/monad b/monad
index ff7a2666e0d03621ba47cb20ac712eff064c85c2..65f14673f74969effb85a8d44a08119c90f44949 100755
Binary files a/monad and b/monad differ
diff --git a/monad.cpp b/monad.cpp
index 8587fbf94d8433a7e03a8cd17f5e3c06bd99faab..26b33756c1975afef01268596101a8c775400577 100644
--- a/monad.cpp
+++ b/monad.cpp
@@ -12,7 +12,8 @@ void processArgs(int argc, const char * const * argv);
 void copyRequiredFiles();
 void getLibs(const vector<string> & libs);
 string updateFolder(const string & folder, bool link);
-string getFolder(const string & folder, const string & searchFirstDir = "", bool link = false);
+string tryGetFolder(string dirAndFolder, const string & target, bool link);
+string getFolder(const string & folder, const string & searchDir = "", bool link = false);
 void importFiles(const string & preservedFolder, const string & theSourceFolder,
                  const string & destFolder, const vector<string> & files);
 void exec_command(const string & command);
@@ -54,19 +55,6 @@ bool optimize = false;
 
 }
 
-string kyleGetDate() {
-	string dateAndTime = "Current Date and Time: ";
-
-	time_t currentTime;
-	struct tm * timeStructure;
-	time(&currentTime);
-	timeStructure = localtime(&currentTime);
-	dateAndTime += asctime(timeStructure);
-
-	return dateAndTime;
-}
-
-
 
 int main(int argc, const char * const * argv)
 {
@@ -333,7 +321,7 @@ void monad::copyRequiredFiles()
 		EXIT_IF_ERROR(rename(gradeFolder.c_str(), tempFolder.c_str())); 
 	}
 
-	exec("/bin/mkdir",gradeFolder.c_str());
+	exec("/bin/mkdir", gradeFolder);
 
 	// Copy and link appropriate files - parsed from config.ini
 	importFiles(tempFolder, "./",         gradeFolder, config["Monad Files"]);
@@ -405,62 +393,65 @@ string monad::updateFolder(const string & folder, bool link)
 {
 	string get = getFolder(folder, "", link);
 	if (opts::update)
-		exec(/*-1,*/ "svn","up", get.c_str());
+		exec("svn", "up", get /*, NULL*/);
 	return get;
 }
 
-string monad::getFolder(const string & folder, const string & searchFirstDir /* = "" */, bool link /* = false */)
+string monad::tryGetFolder(string dirAndFolder, const string & target, bool link)
 {
-	// TODO (toole1): All this stuff is ugly!
-	string target = "./" + folder;
+	if (dirAndFolder[dirAndFolder.length() - 1] == '/')
+		dirAndFolder = dirAndFolder.substr(0, dirAndFolder.size() - 1);
 	
-	// Look in the searchFirstDir folder
-	if (searchFirstDir != "")
+	if (exists(dirAndFolder + "/"))
 	{
-		string searchfirst = "./" + searchFirstDir + folder;
-		if (exists(searchfirst + "/"))
-		{
-			if (!link) return searchfirst + "/";
-			EXIT_IF_ERROR(symlink(searchfirst.c_str(), target.c_str()) != 0);
-			return target + "/";
-		}
+		if (!link) return dirAndFolder + "/";
+		EXIT_IF_ERROR(symlink(dirAndFolder.c_str(), target.c_str()) != 0);
+		return target + "/";
 	}
 
-	// Look in the current folder
-	if (exists(target + "/"))
-		return target + "/";
+	return "";
+}
 
-	// Look in the parent folder
-	string source = "../" + folder;
-	if (exists(source + "/"))
+string monad::getFolder(const string & folder, const string & searchDir /* = "" */, bool link /* = false */)
+{
+	// TODO (toole1): All this stuff is ugly!
+	string target = "./" + folder;
+	string result;
+
+	// Look in the searchDir folder
+	if (searchDir != "")
 	{
-		if (!link) return source + "/";
-		EXIT_IF_ERROR(symlink(source.c_str(), target.c_str()) != 0);
-		return target + "/";
+		result = tryGetFolder(searchDir + "/" + folder, target, link);
+		if (result != "") return result;
+		
+		// Try SVN
+		// Clear out our cache first
+		if (exists(target + "/"))
+			exec("rm", "-rf", target + "/");
+
+		string svndir = config["SVN Root"][0] + "/" + searchDir + "/" + folder;
+
+		int svnstatus = exec("svn", "co", svndir /*, NULL*/);
+		if (svnstatus == 0) return target + "/";
+
+		cerr << "Error: " << folder << " not found." << endl;
+		exit(-1);
 	}
 
-	// Maybe it actually *is* the parent folder
-	string cwd   = getcwdstr();
-	size_t cwd_i = findNthLast(cwd, '/', 2);
-	if (cwd_i != string::npos &&
-	    cwd.length() - cwd_i > folder.length() &&
-	    cwd.compare(cwd_i, folder.length(), folder) == 0)
-	{
-		if (!link) return "../";
-		EXIT_IF_ERROR(symlink("../", target.c_str()) != 0);
+	// Look in the parent folder
+	result = tryGetFolder("../" + folder, target, link);
+	if (result != "") return result;
+
+	// Look in the current folder
+	if (exists(target + "/"))
 		return target + "/";
-	}
 
 	// Look two directories up and over - why not? If the parent folder is
 	// the target source folder for the mp/lab, then the tests or libs
 	// may be two up and over
-	source = "../../" + folder;
-	if (exists(source + "/"))
-	{
-		if (!link) return source + "/";
-		EXIT_IF_ERROR(symlink(source.c_str(), target.c_str()) != 0);
-		return target + "/";
-	}
+	// This also covers the case where it is our parent folder
+	result = tryGetFolder("../../" + folder, target, link);
+	if (result != "") return result;
 
 	// Check Subversion
 
@@ -481,13 +472,12 @@ string monad::getFolder(const string & folder, const string & searchFirstDir /*
 		string svndir = config[svn_config_name][0] + "/" + config[svn_config_subdir][0] + "/" + folder;
 
 		// TODO (toole1): Won't work if user needs to type password
-		int svnstatus = exec(/*-1,*/ "svn","co",svndir.c_str());
+		int svnstatus = exec("svn", "co", svndir /*, NULL*/);
 		if (svnstatus == 0) return target + "/";
 	}
 
 	cerr << "Error: " << folder << " not found." << endl;
 	exit(-1);
-	return "";
 }
 
 
diff --git a/monad_shared.cpp b/monad_shared.cpp
index 98284f3bc3d5bc1954b642345fbe35d4c9dd93c3..229b5207c2be0247da0bb81c5b2ad096ff6313e0 100644
--- a/monad_shared.cpp
+++ b/monad_shared.cpp
@@ -15,7 +15,7 @@ namespace versioninfo
 {
 const char * official_name = "Monad Autograder";
 const char * version_name  = "confession";
-const Version version_num  = Version(2, 1, 3, 3);
+const Version version_num  = Version(2, 1, 4, 0);
 const char * date          = "18 Jan 2012";
 }
 
diff --git a/proxy.cpp b/proxy.cpp
index a5c47306b6879496da5f4d076754b032a86f3dce..ab8896082fa5a6109e71419cfb0c490a1bc0038f 100644
--- a/proxy.cpp
+++ b/proxy.cpp
@@ -502,7 +502,7 @@ void test_execution::child_valgrind()
 	nums_pipe.close_write();
 	
 	start_timeout();
-	exec("valgrind", "--dsymutil=yes", "--trace-children=yes", /*"--log-fd=-1",*/ "-q", "./proxy", test.name(), NULL);
+	exec("valgrind", "--dsymutil=yes", "--trace-children=yes", /*"--log-fd=-1",*/ "-q", "./proxy", test.name());
 }
 
 
diff --git a/util.cpp b/util.cpp
index 1f17813a01ed544567d6e7971aac317e730b81dc..e730cd7df003f9d0f8c995c6643aca1c12bc42fe 100644
--- a/util.cpp
+++ b/util.cpp
@@ -43,6 +43,11 @@ void SET_ERROR_MESSAGE(const char * message)
 	internal::error_prefix = message;
 }
 
+namespace internal
+{
+namespace exec
+{
+
 char * allocateCstr(const string & str)
 {
 	char * cstr = new char[str.size() + 1];
@@ -51,9 +56,217 @@ char * allocateCstr(const string & str)
 	return cstr;
 }
 
+pair<int, int> getFdsFromStream(const ostream * stream)
+{
+	int redirect_fd;
+	int outpipe_fd = -1;
+
+	if (stream == NULL)
+		redirect_fd = -1;
+	else if (stream == &cout || stream == &cerr) // we don't handle cerr right now; it is just left unpiped
+		redirect_fd = STDOUT_FILENO;
+	else
+	{
+		int pipe_fds[2];
+		EXIT_IF_ERROR(pipe(pipe_fds) != 0);
+		redirect_fd = pipe_fds[1];
+		outpipe_fd = pipe_fds[0];
+	}
+
+	return make_pair(redirect_fd, outpipe_fd);
+}
+
+struct exec_timers
+{
+	struct itimerval remaining_real;
+	struct itimerval remaining_virtual;
+	struct itimerval remaining_prof;
+	bool supports_virtual;
+	bool supports_prof;
+	exec_timers() : supports_virtual(true), supports_prof(true) { }
+};
+
+exec_timers get_exec_timers()
+{
+	exec_timers result;
+	
+	EXIT_IF_ERROR(getitimer(ITIMER_REAL, &result.remaining_real));
+	
+	if (getitimer(ITIMER_VIRTUAL, &result.remaining_virtual) != 0)
+	{
+		if (errno == EINVAL)
+		{
+			result.supports_virtual = false;
+			errno = 0;
+		}
+		else
+			exit_if_error_output(__FILE__, __LINE__, "getitimer(ITIMER_VIRTUAL) failed");
+	}
+	
+	if (getitimer(ITIMER_PROF, &result.remaining_prof) != 0)
+	{
+		if (errno == EINVAL)
+		{
+			result.supports_prof = false;
+			errno = 0;
+		}
+		else
+			exit_if_error_output(__FILE__, __LINE__, "getitimer(ITIMER_PROF) failed");
+	}
+
+	return result;
+}
+
+void set_exec_timers(const exec_timers & timers)
+{
+	EXIT_IF_ERROR(setitimer(ITIMER_REAL, &timers.remaining_real, NULL));
+	if (timers.supports_virtual) EXIT_IF_ERROR(setitimer(ITIMER_VIRTUAL, &timers.remaining_virtual, NULL));
+	if (timers.supports_prof)    EXIT_IF_ERROR(setitimer(ITIMER_PROF,    &timers.remaining_prof, NULL));
+}
+
+void redirect_to_fd(const int redirect_fd)
+{
+	if (redirect_fd == -1)
+	{
+		int devnull_fd = open("/dev/null", O_WRONLY | O_NONBLOCK);
+		close(STDOUT_FILENO);
+		close(STDERR_FILENO);
+		dup2(devnull_fd, STDOUT_FILENO);
+		dup2(devnull_fd, STDERR_FILENO);
+		close(devnull_fd);
+	}
+	else if (redirect_fd != STDOUT_FILENO)
+	{
+		close(STDOUT_FILENO);
+		close(STDERR_FILENO);
+		dup2(redirect_fd, STDOUT_FILENO);
+		dup2(redirect_fd, STDERR_FILENO);
+		close(redirect_fd);
+	}
+}
+
+char ** cstr_array_from_vector_string(const string & command, const vector<string> & args)
+{
+	// TODO (toole1): check this doesn't cause a memleak
+	char ** args_cstr = new char*[args.size() + 2];
+	args_cstr[0] = allocateCstr(command);
+	for (size_t i = 0; i < args.size(); i++)
+		args_cstr[i + 1] = allocateCstr(args[i]);
+	args_cstr[args.size() + 1] = NULL;
+	return args_cstr;
+}
+
+} // namespace exec
+} // namespace internal
+
+// heavily refactored, but originally from:
+// http://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c
+int8_t exec(const string & command, const vector<string> & args, ostream * output)
+{
+	using namespace internal;
+	using namespace internal::exec;
+
+	pair<int, int> fds = getFdsFromStream(output);
+	int redirect_fd = fds.first;
+	int outpipe_fd  = fds.second;
+
+	exec_timers timers = get_exec_timers();
+	
+	pid_t pid = fork();
+	EXIT_IF_ERROR(pid < 0);
+	if (pid == 0)
+	{
+		set_exec_timers(timers);
+		redirect_to_fd(redirect_fd);
+		if (outpipe_fd != -1)
+			close(outpipe_fd);
+
+		// Sanitize environment
+		char path[] = "PATH=/bin/:/usr/bin:/usr/local/bin";
+		// Turn off glibc errors default write-to-terminal behaviour, because
+		// it does not get caught by stderr. This instead results in an abort.
+		char redirect_glibc[] = "LIBC_FATAL_STDERR_=1";
+		char * newenv[] = { path, redirect_glibc, NULL };
+		environ = newenv;
+
+		char ** args_cstr = cstr_array_from_vector_string(command, args);
+
+		// Swap out child process image with the command, searching
+		// in the specified path
+		execvp(command.c_str(), args_cstr);
+		
+        // An error occured
+		cerr << "exec(" << '\"' << command << '\"';
+		for (size_t i = 0; i < args.size(); i++)
+			cerr << ", \"" << args[i] << "\"";
+		cerr << ") failed: " << strerror(errno) << endl;
+		exit(-1);
+	}
+	else
+	{
+		// Take the output of the pipe and put it into the *output stream
+		if (outpipe_fd != -1)
+		{
+			EXIT_IF_ERROR(output == NULL);
+			close(redirect_fd);
+
+			vector<char> buffer(1024);
+			ssize_t char_read_count;
+			do
+			{
+				errno = 0;
+				cerr << "START READ" << endl;
+				char_read_count = ::read(outpipe_fd, &buffer[0], buffer.size() - 1);
+				cerr << "END READ " << char_read_count << endl;
+				
+				if (char_read_count < 0 && errno == EINTR) continue;
+				EXIT_IF_ERROR(char_read_count < 0);
+				EXIT_IF_ERROR(static_cast<size_t>(char_read_count) + 1 >= buffer.size());
+				
+				buffer[char_read_count] = '\0';
+				*output << &buffer[0];
+
+			} while (char_read_count > 0);
+		}
+
+		int childExitStatus;
+		/* parent - wait for child - this has all error handling, you
+		 * could just call wait() as long as you are only expecting to
+		 * have one child process at a time.
+		 */
+		pid_t ws = waitpid( pid, &childExitStatus, 0);
+		EXIT_IF_ERROR(ws == -1);
+
+		if (WIFEXITED(childExitStatus)) /* exit code in childExitStatus */
+		{
+			int8_t status = WEXITSTATUS(childExitStatus); /* zero is normal exit */
+			/* handle non-zero as you wish */
+			return status;
+		}
+		else if (WIFSIGNALED(childExitStatus)) /* killed */
+		{
+			// No idea why I'm doing this anymore... if it segfaults, you do too??
+			kill(getpid(), WTERMSIG(childExitStatus));
+			return -1;
+		}
+		else if (WIFSTOPPED(childExitStatus)) /* stopped */
+		{
+			//cout << "exec error: " << __LINE__ << endl;
+			return -1;
+		}
+		else
+			EXIT_IF_ERROR(true);
+		exit(-1);
+	}
+}
+
 // TODO (toole1) this is a total hack, should use execvp like exec() below
+// originally from:
+// http://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c
 int8_t exec(int redirect_fd, const string & command, const vector<string> & args)
 {
+	using namespace internal::exec;
+
 	// For debugging:
 #if 0
 	cerr << "exec(" << '\"' << command << '\"';
diff --git a/util.h b/util.h
index 1439a0082dcbae844a635e8aa73a81ec36d565bc..9da2b7218b8280e5a7d07854bd5c095412b82a2b 100644
--- a/util.h
+++ b/util.h
@@ -138,7 +138,8 @@ inline int8_t exec(int redirect_fd, const string & command, const string & arg1,
 inline int8_t exec(int redirect_fd, const string & command, const string & arg1, const string & arg2, const string & arg3, const string & arg4, const string & arg5) { return exec(redirect_fd, command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str(), arg5.c_str()); }
 inline int8_t exec(int redirect_fd, const string & command, const string & arg1, const string & arg2, const string & arg3, const string & arg4, const string & arg5, const string & arg6) { return exec(redirect_fd, command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str(), arg5.c_str(), arg6.c_str()); }
 int8_t exec(int redirect_fd, const string & command, const vector<string> & args);
-inline int8_t exec(const string & command, const vector<string> & args) { return exec(STDOUT_FILENO, command, args); }
+int8_t exec(const string & command, const vector<string> & args, ostream * output);
+inline int8_t exec(const string & command, const vector<string> & args) { return exec(command, args, &std::cout); }
 
 // FILESYSTEM FUNCTIONS
 void assertExists(const string & path, int exit_code = -1);