diff --git a/src/built_in.c b/src/built_in.c
index 9a466e91501d5877107fb67e308275c4847bcb38..b30c77def4af520db597df3d87aae039be3e13d3 100644
--- a/src/built_in.c
+++ b/src/built_in.c
@@ -35,8 +35,13 @@ int do_pwd(int argc, char** argv) {
 int do_fg(int argc, char** argv) {
   if (!validate_fg_argv(argc, argv))
     return -1;
+  
+  int pid = waitpid(0, 0, 0);
 
-  // TODO: Fill this.
+  if(pid == -1)
+    printf("no such jobs.\n");
+  else
+    printf("%d done\n", pid);
 
   return 0;
 }
diff --git a/src/commands.c b/src/commands.c
index 13e9c330aedcb9d3c1c0979a5b22fd7844516ada..b1eb262fc9843a58eb6493f3ba30dd54dc8c0926 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -2,16 +2,44 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <pthread.h>
 
 #include "commands.h"
 #include "built_in.h"
 
+#define SOCK_PATH "tpf_unix_sock.server"
+#define CLIENT_PATH "tpf_unix_sock.client"
+#define UNIX_PATH_MAX 108
+
+pid_t pID;
+/*
+struct sockaddr_un{
+  unsigned short int sun_family; //AF_UNIX
+  char sun_path[UNIX_PATH_MAX];  //pathname
+};*/
+
+static char PATH[5][1028] = {
+  {"/usr/local/bin/"},
+  {"/usr/bin/"},
+  {"/bin/"},
+  {"/usr/sbin/"},
+  {"/sbin/"}
+};
+
 static struct built_in_command built_in_commands[] = {
   { "cd", do_cd, validate_cd_argv },
   { "pwd", do_pwd, validate_pwd_argv },
   { "fg", do_fg, validate_fg_argv }
 };
 
+void server_thread();
+void client_thread(void* command);
+
 static int is_built_in_command(const char* command_name)
 {
   static const int n_built_in_commands = sizeof(built_in_commands) / sizeof(built_in_commands[0]);
@@ -30,11 +58,23 @@ static int is_built_in_command(const char* command_name)
  */
 int evaluate_command(int n_commands, struct single_command (*commands)[512])
 {
-  if (n_commands > 0) {
-    struct single_command* com = (*commands);
+  struct single_command* com = (*commands);
+  if (n_commands == 1) {
+    //struct single_command* com = (*commands);
 
     assert(com->argc != 0);
 
+    //background processing
+    int background = 0; 
+
+    if(strcmp(com->argv[com->argc-1], "&") == 0){
+      background = 1; 
+    
+      com->argv[com->argc-1] = NULL;
+      com->argc = com->argc-1;
+    }
+
+    //do built_in_command
     int built_in_pos = is_built_in_command(com->argv[0]);
     if (built_in_pos != -1) {
       if (built_in_commands[built_in_pos].command_validate(com->argc, com->argv)) {
@@ -50,12 +90,222 @@ int evaluate_command(int n_commands, struct single_command (*commands)[512])
     } else if (strcmp(com->argv[0], "exit") == 0) {
       return 1;
     } else {
-      fprintf(stderr, "%s: command not found\n", com->argv[0]);
-      return -1;
+      //process creation
+      pID = fork();
+
+      //fork error
+      if(pID == -1){  
+        fprintf(stderr, "fork fail\n");
+       
+      }
+      //child process
+      else if(pID == 0){  
+        path_exec(com);
+
+        fprintf(stderr, "%s: command not found\n", com->argv[0]);
+        exit(0);
+      }
+      //parent process
+      else{  
+        if(background == 1)
+          printf("background pid : %d\n", pID);
+        else
+          waitpid(pID, 0, 0);
+      }
+      return 0;
     }
   }
 
+  //IPC 
+  else if(n_commands >= 2){
+    void* status;
+    pthread_t threads[2];
+    
+    int pid = fork();
+    if(pid == 0){
+      for(int l = 0; l < n_commands; l++){
+        pthread_create(&threads[1], NULL, &client_thread, (void *) com);
+        pthread_join(threads[1], &status);
+        com++;
+      }
+      exit(0);
+    } else{
+        pthread_create(&threads[0], NULL, &server_thread, (void *)&n_commands);
+        waitpid(pid, NULL, 0);
+        pthread_join(threads[0], NULL);
+    }
+
+    return 0;
+  }
+  
+
+  return 0;
+}
+void path_exec(struct single_command* com){
+  if(execv(com->argv[0], com->argv) == -1){ 
+    //need path resoultion 
+    char *tmp = com->argv[0];
+
+    for(int k = 0; k < 5; k++){
+      com->argv[0] = strcat(PATH[k], tmp);
+      if(execv(com->argv[0], com->argv) == -1)
+        com->argv[0] = tmp;
+      else
+        break;
+    }
+  }
+}
+
+void server_thread(){
+  int server_sock, client_sock, len;
+  struct sockaddr_un server_sockaddr;
+  struct sockaddr_un client_sockaddr;
+  char buf[256];
+  memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
+  memset(&client_sockaddr, 0, sizeof(struct sockaddr_un));
+  memset(buf, 0, 256);
+
+  //create domain stream socket
+  server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+  if(server_sock == -1){
+    printf("SOCKET ERROR\n");
+    exit(1);
+  }
+  
+  //bind
+  server_sockaddr.sun_family = AF_UNIX;
+  strcpy(server_sockaddr.sun_path, SOCK_PATH);
+  len = sizeof(server_sockaddr);
+
+  unlink(SOCK_PATH);
+  if(bind(server_sock, (struct sockaddr *) &server_sockaddr, len) == -1){
+    printf("BIND ERROR\n");
+    close(server_sock);
+    exit(1);
+  }
+
+  //listen
+  if(listen(server_sock, 10) == -1){
+    printf("LISTEN ERROR\n");
+    close(server_sock);
+    exit(1);
+  }
+
+  //accept
+  client_sock = accept(server_sock, (struct sockaddr *) &client_sockaddr, &len);
+  if(client_sock == -1){
+    printf("ACCEPT ERROR\n");
+    close(server_sock);
+    close(client_sock);
+    exit(1);
+  }
+
+  dup2(client_sock, STDIN_FILENO);
+  
+  int h = 2;
+  while(h--){  
+  //send data
+  memset(buf, 0, 256);
+  if(send(client_sock, buf, strlen(buf), 0) == -1){
+    printf("SEND ERROR\n");
+    close(server_sock);
+    close(client_sock);
+    exit(1);
+  }
+  
+  //read and print
+  if(recv(client_sock, buf, sizeof(buf), 0) == -1){
+    printf("REC ERROR\n");
+    close(server_sock);
+    close(client_sock);
+    exit(1);
+  }
+  else
+    printf("DATA RECEIVED = %s\n", buf);
+
+ }
+  //close
+  close(server_sock);
+  close(client_sock);
+
   return 0;
+
+}
+
+void client_thread(void* command){
+  int client_sock, len;
+  struct sockaddr_un server_sockaddr;
+  struct sockaddr_un client_sockaddr;
+  char buf[256];
+  memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
+  memset(&client_sockaddr, 0, sizeof(struct sockaddr_un));  
+
+  //create
+  client_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+  if(client_sock == -1){
+    printf("SOCKET ERROR\n");
+    exit(1);
+  }
+
+  //bind
+  client_sockaddr.sun_family = AF_UNIX;
+  strcpy(client_sockaddr.sun_path, CLIENT_PATH);
+  len = sizeof(client_sockaddr);
+
+  unlink(CLIENT_PATH);
+  if(bind(client_sock, (struct sockaddr *) &client_sockaddr, len) == -1){
+    printf("BIND ERROR\n");
+    close(client_sock);
+    exit(1);
+  }
+
+  //set up
+  server_sockaddr.sun_family = AF_UNIX;
+  strcpy(server_sockaddr.sun_path, SOCK_PATH);
+  if(connect(client_sock, (struct sockaddr *) &server_sockaddr, len) == -1){
+    printf("CONNECT ERROR\n");
+    close(client_sock);
+    exit(1);
+  } 
+  
+  void* status;
+  int tempfd = dup(STDOUT_FILENO);
+
+  int pid = fork();
+  if(pid == 0){
+    path_exec(command);
+    exit(0);
+  }
+  else{
+    waitpid(-1, &status, 0);
+    dup2(tempfd, STDOUT_FILENO);
+    close(tempfd);
+  }
+
+  int h = 2;
+  while(h--){
+  //send
+  if(send(client_sock, buf, strlen(buf), 0) == -1){
+    printf("SEND ERROR\n");
+    close(client_sock);
+    exit(1);
+  }
+  
+  //Read
+  memset(buf, 0, sizeof(buf));
+  if(recv(client_sock, buf, sizeof(buf), 0) == -1){
+    printf("RECV ERROR \n");
+    close(client_sock);
+    exit(1);
+  }
+  else
+    printf("DATA RECEIVED = %s\n", buf);
+  }
+  //close
+  close(client_sock);
+ 
+  return 0;
+ 
 }
 
 void free_commands(int n_commands, struct single_command (*commands)[512])
@@ -74,3 +324,4 @@ void free_commands(int n_commands, struct single_command (*commands)[512])
 
   memset((*commands), 0, sizeof(struct single_command) * n_commands);
 }
+
diff --git a/src/main.c b/src/main.c
index 77c78049273e013e278ad9021fa088531b636a97..8f8c0cb4901ef6a0ad6f1fb258d8c323d484c632 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,16 +1,21 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
 
 #include "commands.h"
 #include "built_in.h"
 #include "utils.h"
+#include "signal_handlers.h"
 
 int main()
 {
   char buf[8096];
+  catch_sigint(SIGINT);
+  catch_sigtstp(SIGTSTP);
 
   while (1) {
+    printf("$ ");
     fgets(buf, 8096, stdin);
 
     struct single_command commands[512];
@@ -25,6 +30,7 @@ int main()
     if (ret == 1) {
       break;
     }
+    memset(buf, 0, sizeof(buf));
   }
 
   return 0;
diff --git a/src/signal_handlers.c b/src/signal_handlers.c
index 4b6fe2e073f327917964b5327b6649f74bcbda1e..f98707be0f894047305a274040e40654d3075d16 100644
--- a/src/signal_handlers.c
+++ b/src/signal_handlers.c
@@ -1,11 +1,12 @@
+#include <signal.h>
 #include "signal_handlers.h"
 
-void catch_sigint(int signalNo)
+void catch_sigint(int signalNo)  //process interrupt
 {
-  // TODO: File this!
+  signal(signalNo, SIG_IGN);
 }
 
-void catch_sigtstp(int signalNo)
+void catch_sigtstp(int signalNo)  //process stop
 {
-  // TODO: File this!
+  signal(signalNo, SIG_IGN);
 }