<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -13,6 +13,11 @@
 #include &lt;vector&gt;
 using namespace std;
 
+/**
+ * Check if file is exists.
+ * @param path Path to file to be checked.
+ * @return Yes, if file is existed. Otherwise, No.
+ */
 bool zr_checkFileExists(string path)
 {
 	FILE *fp = NULL;</diff>
      <filename>ZRCommandParser.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -17,12 +17,18 @@
 #include &lt;unistd.h&gt;
 #include &lt;sys/wait.h&gt;
 #include &quot;ZRCommandParser.h&quot;
+#include &lt;pwd.h&gt;
+#include &lt;signal.h&gt;
 using namespace std;
 
 extern int errno;
 extern char** environ;
 
 #ifdef DEBUG
+/**
+ * Output debug message, only works if DEBUG flag is enabled during compiling.
+ * @param msg debug message to show.
+ */
 void debug(string msg)
 {
 	cerr &lt;&lt; &quot;[ZRSh (&quot; &lt;&lt; getpid() &lt;&lt; &quot;)] &quot; &lt;&lt; msg &lt;&lt; endl;
@@ -31,6 +37,9 @@ void debug(string msg)
 void debug(string msg) {}
 #endif
 
+bool interactive = false;
+int waitingpid = 0;
+
 /**
  * This method gives you string trimmed the extra whitespaces in the begin or end.
  * @param str String to be trimmed
@@ -47,6 +56,47 @@ void trim(string&amp; str)
 }
 
 /**
+ * Expand the &quot;~&quot; or &quot;~username&quot; part in the given string to absolute path.
+ * @param str the path to be expanded.
+ * @return the expanded version of input string
+ */
+string expandHomeDirectory(string str)
+{
+	// If it's already an aboslute path, pass.
+	if (str[0] == '/')
+		return str;
+		
+	// Oh? User directory...
+	if (str[0] == '~')
+	{
+		if (str.size() == 1)
+		{
+			string home = string(getenv(&quot;HOME&quot;));
+			return home;
+		}
+		else if (str[1] == '/')
+		{
+			string home = string(getenv(&quot;HOME&quot;));
+			return home + str.substr(1);
+		}
+		else
+		{
+			int pos = str.find(&quot;/&quot;);
+			string username = str.substr(1, pos - 1);
+			struct passwd *record = getpwnam(username.c_str());
+			string path;
+			if (record &amp;&amp; record-&gt;pw_dir)
+				path = string(record-&gt;pw_dir) + str.substr(pos);
+			else
+				path = str;
+			return path;
+		}
+	}
+	
+	return str;
+}
+
+/**
  * Execute the command
  * @param r A ZRCommandParserResultPart object to be executed.
  */
@@ -54,22 +104,35 @@ void execute(ZRCommandParserResultPart r)
 {
 	char **arg_list = (char**)malloc(sizeof(char*) * (r.arguments.size() + 1));
 	
-	// Use MYPATH is it is existed, or we fallback to ordinary PATH
 	char *searchPath = getenv(&quot;MYPATH&quot;);
+	// MYPATH is existed, but we need to change the delimiter to ordinary ':'
+	if (searchPath)
+	{
+		int len = strlen(searchPath);
+		for(int i=0;i&lt;len;i++)
+			if (searchPath[i] == '$')
+				searchPath[i] = ':';
+	}
+	
+	// MYPATH is not found, use PATH instead.
 	if (!searchPath)
+	{
+		cerr &lt;&lt; &quot;[ZRSh] MYPATH is not found, fallback to PATH&quot; &lt;&lt; endl;
 		searchPath = getenv(&quot;PATH&quot;);
-		
+	}
+	
+	// Nothing I can use :( Let's just find it in current directory.
 	if (!searchPath)
 	{
 		searchPath = (char*)malloc(sizeof(char) * 1);
 		strcpy(searchPath, &quot;&quot;);
 	}
 
-	// Prepare arguments list
 	string path = r.getAbsolutePath(string(searchPath));
 	if (!searchPath)
 		free(searchPath);
 	
+	// Prepare arguments list
 	arg_list[0] = (char*)malloc(path.length() + 1);
 	strcpy(arg_list[0], path.c_str());
 	arg_list[0][path.length()] = NULL;
@@ -80,8 +143,9 @@ void execute(ZRCommandParserResultPart r)
 		strcpy(arg_list[i+1], r.arguments[i].c_str());
 		arg_list[i+1][r.arguments[i].length()] = NULL;
 	}
-	arg_list[r.arguments.size() + 1] = NULL;
+	arg_list[r.arguments.size() + 1] = NULL; // Don't forget the tailing NULL.
 	
+	// Handles redirection
 	FILE* fp;
 	int fd;
 	
@@ -135,7 +199,10 @@ void spawn(ZRCommandParserResultPart r)
 	else if (pid &gt; 0)
 	{
 		if (!r.background)
+		{
+			waitingpid = pid;
 			waitpid(pid, NULL, NULL);
+		}
 	}
 	else
 		cout &lt;&lt; &quot;[ZRSh] Sorry, fork failed!&quot; &lt;&lt; endl;
@@ -201,6 +268,25 @@ int spawn_for_pipe(vector&lt;ZRCommandParserResultPart&gt;::iterator begin, vector&lt;ZRC
 	return -1;
 }
 
+/**
+ * SIGINT(Ctrl + C) Handler, kill the waiting process if not in interactive mode. Otherwise, exit ZeroShell.
+ * @params sig signal number (In our case, this will always be SIGINT.)
+ */
+void sigint_handler(int sig)
+{
+	if (!interactive)
+	{
+		cout &lt;&lt; endl &lt;&lt; &quot;[ZRSh] Sending SIGINT to Kill the foreground process...&quot; &lt;&lt; endl;
+		kill(waitingpid, SIGINT);
+		cout &lt;&lt; endl;
+	}
+	else
+	{
+		cout &lt;&lt; endl &lt;&lt; &quot;[ZRSh] Received SIGINT, bye!&quot; &lt;&lt; endl;
+		exit(0);
+	}
+}
+
 int main()
 {
 	cout &lt;&lt; &quot;Welcome to ZeroShell(ZRSh) 1.0&quot; &lt;&lt; endl;
@@ -215,11 +301,16 @@ int main()
 	char hostname[1024] = {0};
 	gethostname(hostname, 1023);
 	string home = string(getenv(&quot;HOME&quot;));
+	
+	// Install SIGINT catcher
+	signal(SIGINT, sigint_handler);
+	
 	cout &lt;&lt; &quot;Done, dropping you to shell.&quot; &lt;&lt; endl &lt;&lt; endl;
 	
 	// Command input routine
 	while(true)
 	{
+		interactive = true;
 		ostringstream oss;
 		char *path_c = (char*)malloc(sizeof(char) * 1024);
 		size_t size = 1024;
@@ -246,6 +337,7 @@ int main()
 		free(input);
 		if (command == &quot;&quot;) continue;
 		add_history(command.c_str());
+		interactive = false;
 		
 		// Parse the input command
 		ZRCommandParserResult r = parser.parse(command);
@@ -268,9 +360,11 @@ int main()
 		else if (r.parts[0].command == &quot;cd&quot;)
 		{
 			if (r.parts[0].arguments.size() == 0)
-				chdir(&quot;~&quot;);
+				chdir(home.c_str());
 			else
-				chdir(r.parts[0].arguments[0].c_str());
+			{
+				chdir(expandHomeDirectory(r.parts[0].arguments[0]).c_str());
+			}
 		}
 		else if (r.parts[0].command == &quot;setenv&quot;)
 		{
@@ -316,7 +410,10 @@ int main()
 					exit(0);
 				}
 				else
+				{
+					waitingpid = pid;
 					waitpid(pid, NULL, NULL);
+				}
 			}
 		}
 	}</diff>
      <filename>zrsh.cpp</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>3654bd7ae0ddf0ef037231ca21783d7259e8e932</id>
    </parent>
  </parents>
  <author>
    <name>Chien-An Cho (Zero Cho)</name>
    <email>itszero@gmail.com</email>
  </author>
  <url>http://github.com/itszero/ZeroShell/commit/7734f56dca142273814c6d69017b8c39150f5aa4</url>
  <id>7734f56dca142273814c6d69017b8c39150f5aa4</id>
  <committed-date>2009-04-14T10:43:19-07:00</committed-date>
  <authored-date>2009-04-14T10:43:19-07:00</authored-date>
  <message>add more decription of the method</message>
  <tree>2d625be66f43b8fd142d80ab662bd145bcda17c7</tree>
  <committer>
    <name>Chien-An Cho (Zero Cho)</name>
    <email>itszero@gmail.com</email>
  </committer>
</commit>
