Skip to content
Snippets Groups Projects
Select Git revision
  • 017340409b3f128fb71e38ad5ed0fe9390e19bec
  • master default
2 results

commands.c

Blame
  • Forked from sce213ta / mysh-1
    Source project has a limited visibility.
    commands.c 5.16 KiB
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    #include <unistd.h>
    #include <signal.h>
    #include <pthread.h>
    #include <sys/un.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/socket.h>
    #include "commands.h"
    #include "built_in.h"
    
    #define SOCK_PATH "tpf_unix_sock.socket"
    #define CLIENT_PATH "tpf_unix_sock.client"
    
    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 }
    };
    
    char path_1[5][256]={"/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"};
    int status=0;
    
    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]);
    
      for (int i = 0; i < n_built_in_commands; ++i) {
        if (strcmp(command_name, built_in_commands[i].command_name) == 0) {
          return i;
        }
      }
    
      return -1; // Not found
    }
    
    //int evaluate_command(int n_commands, struct single_command (*commands)[512]);
    //void client(struct single_command (*commands)[512]);
    
    void *server(void *arg)
    {
      int server_socket,client_socket,rc;
      int backlog = 10;
      struct sockaddr_un server_addr,client_addr;
      server_socket=socket(AF_UNIX,SOCK_STREAM,0);
      memset(&server_addr,0,sizeof(server_addr));
      server_addr.sun_family=AF_UNIX;
      strcpy(server_addr.sun_path,SOCK_PATH);
      unlink(SOCK_PATH);
    
      while(1)
      {
        if(bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))==-1)
        {
          exit(0);
        }
    
        rc = listen(server_socket, backlog);
        if (rc == -1)
        { 
          close(server_socket);
          exit(1);
        }
    
        if(listen(server_socket,5)==-1)
        {
          exit(0);
        }
    	
        int client_addr_size=sizeof(client_addr);
        client_socket=accept(server_socket,(struct sockaddr*)&client_addr,&client_addr_size);
      
        if(fork()==0)
        {
          close(0);
          dup2(client_socket,0);
          struct single_command proc[512];
          struct single_command *b=(struct single_command *)arg;
          memcpy(&proc[0],b,sizeof(struct single_command));
          evaluate_command(1,&proc);
          exit(0);
        }
    
        wait(&status);
        close(client_socket);
        close(server_socket);
        pthread_exit(0);
        exit(0);
      }
    }
    
    void client(struct single_command (*commands)[512])
    {
      int client_socket,rc,len;
      struct sockaddr_un server_sockaddr, client_sockaddr;
      struct single_command a[512];
      struct single_command b[512];
      struct single_command *c1=(*commands);
      struct single_command *c2=&(*commands)[1];
      memcpy(&a[0],c1,sizeof(struct single_command));
      memcpy(&b[0],c2,sizeof(struct single_command));
      pthread_t threadId;
      if(pthread_create(&threadId,NULL,server,&b)<0)
      {
        perror("error \n");
        exit(0);
      }
    	
      if(!fork())
      {
        client_socket=socket(AF_UNIX,SOCK_STREAM,0);
    
        if (client_socket == -1)
        {
          exit(1);
        }
    
        client_sockaddr.sun_family = AF_UNIX;
        len = sizeof(client_sockaddr);
        unlink(CLIENT_PATH);
        rc = bind(client_socket, (struct sockaddr *) &client_sockaddr, len);
        if (rc == -1)
        {
          close(client_socket);
          exit(1);
        }
    
        memset(&server_sockaddr,0,sizeof(server_sockaddr));
        server_sockaddr.sun_family=AF_UNIX;
        strcpy(server_sockaddr.sun_path,SOCK_PATH);
    
        while(connect(client_socket,(struct sockaddr*)&server_sockaddr,sizeof(server_sockaddr))==-1);
    
        if(!fork())
        {			
          close(0);close(1);
          dup2(client_socket,1);
          evaluate_command(1,&a);
          pthread_exit(0);exit(0);
        }
    
        wait(&status);
        pthread_join(threadId,NULL);
        close(client_socket);
        exit(0);
      }
      wait(&status);
    }
    
    int evaluate_command(int n_commands, struct single_command (*commands)[512])
    {
      if(n_commands>1)
      {
        client(commands);
      }
      else if (n_commands ==1)
      {
        struct single_command* com = (*commands);
        assert(com->argc != 0);
        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))
          {
            if (built_in_commands[built_in_pos].command_do(com->argc, com->argv) != 0)
            {
              fprintf(stderr, "%s: Error \n", com->argv[0]);
    	}
          } 
          else
          {
    	fprintf(stderr, "%s: Error \n", com->argv[0]);
    	return -1;
          }
        }
        else if (strcmp(com->argv[0], "") == 0)
        {
          return 0;
        } 
        else if (strcmp(com->argv[0], "exit") == 0)
        {
          return 1;
        } 
        else if (com->argc>0)
        {
          pid_t pid=fork();
          if(pid==0)
          {
    	execv(com->argv[0],com->argv);
    	for(int i=0;i<5;i++)
    	{
    	  char *temp;
    	  temp=strcat(path_1[i],"/");
    	  temp=strcat(temp,com->argv[0]);
    	  execv(temp,com->argv);
    	}
    	exit(1);
          }
          else
          {
    	waitpid(pid,0,0);
          }
        }
        else
        {
          fprintf(stderr, "%s: Fail \n", com->argv[0]);
          return -1;
        }
      }
      return 0;
    }
    
    void free_commands(int n_commands, struct single_command (*commands)[512])
    {
      for (int i = 0; i < n_commands; ++i)
      {
        struct single_command *com = (*commands) + i;
        int argc = com->argc;
        char** argv = com->argv;
    
        for (int j = 0; j < argc; ++j)
        {
          free(argv[j]);
        }
    
        free(argv);
      }
    
      memset((*commands), 0, sizeof(struct single_command) * n_commands);
    }