diff --git a/Makefile b/Makefile index 96675da65e4c4973a65d6df6bc2ee2b1523751ed..cf5d0d4fcda42042114cb4f95457aa1327402a12 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ # For implementation -CC=gcc -std=c99 +# c99 -> gnu99 +CC=gcc -std=gnu99 CFLAGS=-I./src -I./include LIB=-lpthread OBJ=./src/utils.o ./src/commands.o ./src/built_in.o ./src/signal_handlers.o diff --git a/include/built_in.h b/include/built_in.h index b2df0aa845f50b0ba45508d0418a3fbe9643579c..36f474a28ea6c04db7aa5ed8d43c738a1f734a1a 100644 --- a/include/built_in.h +++ b/include/built_in.h @@ -1,6 +1,9 @@ #ifndef BUILT_IN_H_ #define BUILT_IN_H_ +int *child; + + typedef int (*built_in_command_do)(int, char**); typedef int (*built_in_command_validate)(int, char**); diff --git a/include/commands.h b/include/commands.h index c0b66fecb66fd5863c4e9b9ab363c3a053eb37bc..b005ede651d82531e24dd9c44b4862aed97820d6 100644 --- a/include/commands.h +++ b/include/commands.h @@ -7,6 +7,9 @@ struct single_command char** argv; }; +void* server(void * com); +void* client(void * com); + int evaluate_command(int n_commands, struct single_command (*commands)[512]); void free_commands(int n_commands, struct single_command (*commands)[512]); diff --git a/src/built_in.c b/src/built_in.c index 9a466e91501d5877107fb67e308275c4847bcb38..ace0bd0dd79230afd423d0b89958b9076903074b 100644 --- a/src/built_in.c +++ b/src/built_in.c @@ -1,10 +1,12 @@ #include <stdio.h> #include <string.h> - +#include <wait.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <linux/limits.h> +#include <sys/sysinfo.h> + #include "built_in.h" @@ -36,9 +38,42 @@ int do_fg(int argc, char** argv) { if (!validate_fg_argv(argc, argv)) return -1; - // TODO: Fill this. + if(*child == 0){return 0;} + int status; + + printf("Background pid(%d) running\n",*child); + + waitpid(*child,&status,0); + + printf("Background pid(%d) Done\n",*child); + +/* Double fork - hard to implement + + sleep(0.5); + int status; + struct sysinfo cur; + sysinfo(&cur); + int curprocess = cur.procs; + int before = curprocess; + + printf("before %d\n",curprocess); + printf("Background process running\n"); + + + while(before == curprocess) + { + sysinfo(&cur); + curprocess = cur.procs; + sleep(1); + } + + printf("Background process Done\n"); + printf("after %d\n",curprocess); + +*/ return 0; + } int validate_cd_argv(int argc, char** argv) { diff --git a/src/commands.c b/src/commands.c index 13e9c330aedcb9d3c1c0979a5b22fd7844516ada..158bc162cd5305cc98beac985021a54d6e52a1db 100644 --- a/src/commands.c +++ b/src/commands.c @@ -2,16 +2,205 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <unistd.h> +#include <wait.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <pthread.h> +#include <netdb.h> +#include <sys/un.h> + +#define SERVER_PATH "/tmp/server" #include "commands.h" #include "built_in.h" +//port number +char port[30]; +//thread signal +int end=0; + + 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(void * comm){ + + + struct single_command * com = (struct single_command*)comm; + + printf(" Server start\n"); +/* TCP/IP + + int serv_sock; + int clnt_sock; + struct sockaddr_in serv_addr; + struct sockaddr_in clnt_addr; + + socklen_t clnt_addr_size; + + memset(&serv_addr,0,sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(atoi(port)); + + //create socket + serv_sock = socket(PF_INET,SOCK_STREAM,0); + //bind + bind(serv_sock,(struct sockaddr*)&serv_addr , sizeof(serv_addr)); + //listen + listen(serv_sock,5); + + clnt_addr_size = sizeof(clnt_addr); + //accept + clnt_sock = accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_size); +*/ + + int sd; + int sd2; + struct sockaddr_un serveraddr; + + sd = socket(AF_UNIX,SOCK_STREAM,0); + memset(&serveraddr,0,sizeof(serveraddr)); + serveraddr.sun_family = AF_UNIX; + strcpy(serveraddr.sun_path,SERVER_PATH); + + bind(sd,(struct sockaddr *)&serveraddr,SUN_LEN(&serveraddr)); + + listen(sd,5); + +/* + struct sockaddr_un cliaddr; + socklen_t len = sizeof(struct sockaddr_un); +*/ + sd2 = accept(sd,NULL,NULL); + printf(" accept\n"); + + int pid; + //server child + if( (pid = fork())== 0 ){ + + + com->argv[com->argc] = NULL; + //dup2(clnt_sock,1); + dup2(sd2,1); + + + if(strcmp(com->argv[0],"pwd")==0) + { + execv("/bin/pwd",com->argv); + } + + else{ + execv(com->argv[0],com->argv); + } + + }else{ + + sleep(2); + /* + close(clnt_sock); + close(serv_sock); + clnt_sock=-1; + serv_sock=-1; + */ + close(sd2); + close(sd); + sd=-1; + sd2=-1; + unlink(SERVER_PATH); + printf(" Sent success\n"); + end ++; + end ++; + + } + +} + + +void *client(void * comm){ + + +sleep(0); + + struct single_command* com = (struct single_command *)comm; + + printf(" client start\n"); + + /* TCP/IP + + int sock; + struct sockaddr_in serv_addr; + int str_len; + + sock = socket(PF_INET,SOCK_STREAM,0); + + memset(&serv_addr , 0 , sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + + //Domain + struct hostent *host_entry; + int host_ip = 0; + if((host_ip = inet_addr("ajou-VirtualBox"))==-1) + { + host_entry = gethostbyname("ajou-VirtualBox"); + if(host_entry != NULL) + host_ip = *((unsigned long *)(host_entry->h_addr_list[0])); + } + + + serv_addr.sin_addr.s_addr = host_ip; + //TCP/IP("10.0.2.15"); + serv_addr.sin_port = htons(atoi(port)); + + connect(sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); +*/ + int sock; + struct sockaddr_un serveraddr; + + sock = socket(AF_UNIX,SOCK_STREAM,0); + memset(&serveraddr,0,sizeof(serveraddr)); + serveraddr.sun_family = AF_UNIX; + strcpy(serveraddr.sun_path,SERVER_PATH); + + + + connect(sock,(struct sockaddr *)&serveraddr,SUN_LEN(&serveraddr)); + + int pid; + + + + if((pid = fork())==0) + { + com->argv[com->argc]=NULL; + dup2(sock,0); + execv(com->argv[0],com->argv); + + }else + { + sleep(2); + close(sock); + sock=-1; + printf(" Client Receive\n"); + end++; + } + + +} + + + + + 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]); @@ -26,35 +215,220 @@ static int is_built_in_command(const char* command_name) } /* - * Description: Currently this function only handles single built_in commands. You should modify this structure to launch process and offer pipeline functionality. + * Description: Currently : */ int evaluate_command(int n_commands, struct single_command (*commands)[512]) { if (n_commands > 0) { struct single_command* com = (*commands); +// printf("%d %s %s %s \n",com->argc,com->argv[0],com->argv[1],com->argv[2]); + assert(com->argc != 0); + // cd 0 , pwd 1 , fg 2 , another -1 int built_in_pos = is_built_in_command(com->argv[0]); - if (built_in_pos != -1) { + + +//modify + if ((built_in_pos != -1)&&(n_commands==1)) { if (built_in_commands[built_in_pos].command_validate(com->argc, com->argv)) { + + + + if (built_in_commands[built_in_pos].command_do(com->argc, com->argv) != 0) { fprintf(stderr, "%s: Error occurs\n", com->argv[0]); } - } else { + + + + }else { fprintf(stderr, "%s: Invalid arguments\n", com->argv[0]); return -1; } - } else if (strcmp(com->argv[0], "") == 0) { + } + // another argv[0] + else if (strcmp(com->argv[0], "") == 0) { return 0; } else if (strcmp(com->argv[0], "exit") == 0) { return 1; } else { - fprintf(stderr, "%s: command not found\n", com->argv[0]); - return -1; - } - } + + + + //PIPE MODE + // com->argv[] (com+1)->argv[] + if(n_commands == 2) + { + + + pthread_t p_thread[2]; + + int thr_id; +/* + printf("Enter the port number to use (5000~15000)\n"); + fgets(port,sizeof(port),stdin); + port[sizeof(port)-1]='\0'; +*/ + + pthread_create(&p_thread[0],NULL,server,(void *)(com)); + pthread_create(&p_thread[1],NULL,client,(void *)(com+1)); + + pthread_detach(p_thread[0]); + pthread_detach(p_thread[1]); + + while(end != 3){ + sleep(2); + } + sleep(1); + printf("END\n"); + + + end = 0; + return -1; + } // socket + + //mode - NO PIPE + else{ + // If background process + if(!strcmp(com->argv[(com->argc)-1], "&")) + { + + int status; + int pid; + // copy argv + char*copy_argv[(com->argc)]; + + int c =0; + + for(;c<com->argc;c++) + copy_argv[c]=malloc(sizeof(char)*100); + copy_argv[(com->argc)-1] =NULL; + // path copy + for(c=0; c< ( com->argc) -1 ; c++ ) + { strcpy(copy_argv[c],com->argv[c]); + } + + + /* Double fork version - Hardly know Demon + //1st child + if ((pid = fork() )== 0) + { + sleep(0.8); + + //2st child + if( (pid = fork()) == 0 ) + { + sleep(0.8); + execv(com->argv[0],copy_argv); + } + + else + { + //1st exit + exit(1); + } + } + //parent shell wait + else + { + //foreward process + printf("BackGround process ID %d\n",pid+1); + + wait(&status); + + } + */ + + //child + if( (pid = fork()) == 0 ) + { + execv(com->argv[0],copy_argv); + } + //parent no wait only sleep + else{ + //child = malloc (sizeof(int*)); + *child = pid; + printf("Background pid(%d)\n",pid); + sleep(1); + + //copy free + for(c=0; c < com->argc ; c++) + free(copy_argv[c]); + + return -1; + } + + } + + + + + + // Start create process - No background + else{ + int status; + int pid; + // copy argv + char *copy_argv[(com->argc)+1]; + int c =0; + //copy_argv = malloc(sizeof(char*)); + for(;c<(com->argc)+1;c++) + copy_argv[c]=malloc(sizeof(char)*100); + + + //execv last NULL + copy_argv[(com->argc)] = NULL; + + + for(c=0 ;c < (com->argc) ; c++) + strcpy(copy_argv[c] , com->argv[c]); + + //child + if( ( pid = fork() ) ==0 ) + { + + if(execv(com->argv[0],copy_argv) == -1) + { + printf("execv Fail \n"); + exit(0); + } + + } // child + + //parent + else { + + + // setbuf(stdin,) + + + waitpid(pid,&status,0); + + char c ; + rewind(stdin); + rewind(stdout); + + //free(copy_argv); + for(c=0 ; c< com->argc ; c++) + free(copy_argv[c]); + + return -1; + } + } + + // NO background create process + + + /* + fprintf(stderr, "%s: command not found\n", com->argv[0]); + return -1; + */ + } // mode + } + } return 0; } diff --git a/src/main.c b/src/main.c index 77c78049273e013e278ad9021fa088531b636a97..0ef07205cd6c77acb35c50d2a8b757bb33c7eef4 100644 --- a/src/main.c +++ b/src/main.c @@ -1,18 +1,72 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <signal.h> +#include <termios.h> + #include "commands.h" #include "built_in.h" #include "utils.h" +#include "signal_handlers.h" + int main() { - char buf[8096]; + char buf [8096]; + //signal handle + + + struct sigaction ctrc; + struct sigaction ctrz; + + ctrc.sa_handler = catch_sigint; + ctrz.sa_handler = catch_sigtstp; + + sigemptyset(&ctrc.sa_mask); + sigemptyset(&ctrz.sa_mask); + + ctrc.sa_flags = 0; + ctrz.sa_flags = 0; + + if(sigaction (SIGINT,&ctrc,0) == -1) + { + printf("signal (SIGINT) error\n"); + return -1; + } + + if(sigaction (SIGTSTP,&ctrz,0) == -1) + { + printf("signal (SIGTSTP) error\n"); + return -1; + } + + + stdin_copy = dup(STDIN_FILENO); + +// signal + child = malloc(sizeof(int*)); + *child = 0; + int n=1; + while (n) { + + + if(n != 1) + { + tcdrain(stdin_copy); + tcflush(stdin_copy,TCIFLUSH); + } - while (1) { - fgets(buf, 8096, stdin); + sigsetjmp(sig,1); + printf("$"); + fgets(buf, 8096, stdin); + + n++; +// struct single_command commands[512]; int n_commands = 0; mysh_parse_command(buf, &n_commands, &commands); diff --git a/src/signal_handlers.c b/src/signal_handlers.c index 4b6fe2e073f327917964b5327b6649f74bcbda1e..5f1c21e52d5caafeb0f6a240cb9868da5bb4cc26 100644 --- a/src/signal_handlers.c +++ b/src/signal_handlers.c @@ -1,11 +1,47 @@ +#include <signal.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> + +#include <termios.h> + #include "signal_handlers.h" + void catch_sigint(int signalNo) { - // TODO: File this! + if(signalNo!= SIGINT) + printf("Unvalid signal\n"); + + tcdrain(stdin_copy); + tcflush(stdin_copy,TCIFLUSH); + + printf("\n"); + siglongjmp(sig,1); + +// whie ( (c=getchar()) != '\n' ){} + + +// printf("%d\n",getpid()); + } void catch_sigtstp(int signalNo) { - // TODO: File this! + + if(signalNo!= SIGTSTP) + printf("Unvalid signal\n"); + + tcdrain(stdin_copy); + tcflush(stdin_copy,TCIFLUSH); + + printf("\n"); + siglongjmp(sig,1); + + + +// while ( (c=getchar() != '\n' ) ){} + + +// printf("%d\n",getpid()); } diff --git a/src/signal_handlers.h b/src/signal_handlers.h new file mode 100644 index 0000000000000000000000000000000000000000..7723f245ba19b585b2bca338b381a4bf9e8e0a01 --- /dev/null +++ b/src/signal_handlers.h @@ -0,0 +1,12 @@ +#ifndef SIGNAL_HANDLERS_H +#define SIGNAL_HANDLERS_H + +#include <setjmp.h> + +sigjmp_buf sig; + +int stdin_copy; +void catch_sigint(int signalNo); +void catch_sigtstp(int signalNo); + +#endif