SHARE
TWEET

Untitled

a guest May 22nd, 2019 81 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <sys/wait.h>
  2. #include <sys/stat.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <fcntl.h>
  8. #include <signal.h>
  9.  
  10. #define LSH_TOK_BUFSIZE 64
  11. #define LSH_TOK_DELIM " \t\r\n\a"
  12. #define MAX_COMMAND_HISTORY 20
  13.  
  14. int lsh_cd(char **args);
  15. int lsh_help(char **args);
  16. int lsh_exit(char **args);
  17.  
  18. char *builtin_str[] = {
  19.     "cd",
  20.     "help",
  21.     "exit" };
  22.  
  23. int(*builtin_func[])(char **) = {
  24.     &lsh_cd,
  25.     &lsh_help,
  26.     &lsh_exit,
  27. };
  28.  
  29. int lsh_num_builtins() /*Funkcja zwraca ilość wbudowanych poleceń.*/
  30. {
  31.     return sizeof(builtin_str) / sizeof(char *);
  32. }
  33.  
  34. char *lsh_get_history_dir(void) /*Zwraca ścieżkę do pliku z historią poleceń*/
  35. {
  36.     char filepath[] = "bash_history.txt";
  37.     char *homedir = getenv("HOME");
  38.     char *path = malloc((strlen(filepath) + strlen(homedir) + 1) * sizeof(char));
  39.     strcpy(path, homedir);
  40.     strcat(path, "/");
  41.     strcat(path, filepath);
  42.     return path;
  43. }
  44.  
  45. int lsh_cd(char **args) /*Obsługa polecenia cd.*/
  46. {
  47.     if (args[1] == NULL)
  48.         fprintf(stderr, "lsh: expected argument to \"cd\"\n");
  49.     else if (chdir(args[1]) != 0)
  50.         perror("lsh");
  51.     return 1;
  52. }
  53.  
  54. int lsh_help(char **args) /*Obsługa polecenia help.*/
  55. {
  56.     puts("Dostepne komendy: \n");
  57.     for (int i = 0; i < lsh_num_builtins(); i++)
  58.         printf("  %s\n", builtin_str[i]);
  59.     printf("  history\n");
  60.     puts("Program przygotowany na zajecia z Systemow Operacyjnych przez:");
  61.     puts("Emilie Jutkiewicz\nDawida Rydzewskiego\nRadoslawa Skiepko");
  62.     return 1;
  63. }
  64.  
  65. void lsh_history(int sig) /*Obsługa polecenia history.*/
  66. {
  67.     if (sig == SIGUSR1) //Funkcję wywołuje sygnał SIGUSR1, funkcja jest 'handlerem' tego sygnału.
  68.     {
  69.         puts("");
  70.         int f = open(lsh_get_history_dir(), O_RDONLY);
  71.         if (f != -1)
  72.         {
  73.             char buf[100];
  74.             while (read(f, buf, 100))
  75.                 write(1, buf, strlen(buf));
  76.             puts("");
  77.             close(f);
  78.         }
  79.     }
  80. }
  81.  
  82. int lsh_exit(char **args) /*Obsługa polecenia exit.*/
  83. {
  84.     return 0;
  85. }
  86.  
  87. int lsh_launch(char **args, int flag) /*Funkcja uruchamiająca polecenia.*/
  88. {
  89.     pid_t pid, wpid;
  90.     int status, background_flag = 0, position = 0, position2 = 0;
  91.     pid = fork();
  92.     while (args[position] != NULL)
  93.         position++;
  94.     /* Pętla sprawdza czy wystąpiło żadąnie działania w tle.*/
  95.     while (args[position - 1][position2] != '\0')
  96.         position2++;
  97.     if (args[position - 1][position2 - 1] == '&')
  98.     {
  99.         background_flag = 1; /*Jeśli wytąpiło zmienia flagę działania w tle.*/
  100.         args[position - 1][position2 - 1] = '\0';
  101.     }
  102.     if (pid == 0)
  103.     {
  104.         if (flag != -1) /*Jeśli w poleceniu wystąpiło przekierowanie ">>", zmienna*/
  105.         {               /*flag przyjmuje wartość w którym nastąpiło.*/
  106.             int fd1;
  107.             if ((fd1 = open(args[flag + 1], O_WRONLY | O_CREAT | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
  108.             {
  109.                 perror(args[flag + 1]);
  110.                 exit(EXIT_FAILURE);
  111.             }
  112.             dup2(fd1, 1); /*Zmiana standardowego wyjścia na przekazane po znakach ">>".*/
  113.             close(fd1);
  114.             args[flag] = args[flag + 1] = NULL; /*Usunięcie z tablicy poleceń przekierowania.*/
  115.         }
  116.         if (execvp(args[0], args) == -1) /*Uruchamianie poleceń, w przypadku błędu wyświetla error.*/
  117.             perror("lsh");
  118.         exit(EXIT_FAILURE);
  119.     }
  120.     else if (pid < 0)
  121.         perror("lsh");
  122.     else if (background_flag == 0) /*Gdy wystąpiło żądanie działania w tle program nie wchodzi*/
  123.         do                         /*w pętle i nie czeka na zakończenie uruchomionego procesu.*/
  124.         {
  125.             wpid = waitpid(pid, &status, WUNTRACED);
  126.         } while (!WIFEXITED(status) && !WIFSIGNALED(status));
  127.         return 1;
  128. }
  129.  
  130. int lsh_loop_pipe(char ***cmd) /*Pętla wykonująca nielimitowane potoki*/
  131. {
  132.     int p[2];
  133.     pid_t pid, wpid;
  134.     int status;
  135.     int fd_in = 0;
  136.     while (*cmd != NULL)
  137.     {
  138.         pipe(p);
  139.         pid = fork();
  140.         if (pid == 0)
  141.         {
  142.             dup2(fd_in, 0); /*Zmiana wejścia zgodnie z starszym*/
  143.             if (*(cmd + 1) != NULL)
  144.                 dup2(p[1], 1);
  145.             close(p[0]);
  146.             execvp((*cmd)[0], *cmd); /*Wykonanie polecenia*/
  147.             exit(EXIT_FAILURE);
  148.         }
  149.         else if (pid < 0)
  150.         {
  151.             perror("lsh");
  152.         }
  153.         else
  154.         {
  155.             do
  156.             {
  157.                 wpid = waitpid(pid, &status, WUNTRACED);
  158.             } while (!WIFEXITED(status) && !WIFSIGNALED(status));
  159.  
  160.             close(p[1]);
  161.             fd_in = p[0]; /*Zapisanie wejścia dla następnej komendy*/
  162.             cmd++;
  163.         }
  164.     }
  165. }
  166.  
  167. int lsh_execute(char **args) /*Funkcja sprawdza czy wystąpiły predefiniowane polecenia,*/
  168. {                            /*przekierowania lub potoki.*/
  169.     int second_position, history_flag, output_flag;
  170.     char tmp_history[] = "history";
  171.     for (int first_position = 0; args[first_position] != NULL; first_position++)
  172.     { /*Pętla przechodząca po wszystkich argumentach.*/
  173.         history_flag = 1;
  174.         output_flag = 0;
  175.         for (second_position = 0; second_position < 7; second_position++)
  176.             if (args[first_position][second_position] != tmp_history[second_position])
  177.             { /*Sprawdza czy wystąpiło polecenie history.*/
  178.                 history_flag = 0;
  179.                 break;
  180.             }
  181.         if (history_flag == 1)
  182.         {
  183.             if (signal(SIGUSR1, lsh_history) == SIG_ERR) /*Definiowanie obsługi sygnału.*/
  184.                 printf("Nie udalo sie obsluzyc sygnalu");
  185.             raise(SIGUSR1); /*Wywołanie wyświetlenia historii poleceń.*/
  186.             if (args[first_position + 1] == NULL)
  187.                 args[first_position] = NULL;
  188.             else
  189.                 for (int i = first_position; args[i + 1] != NULL; i++)
  190.                 {
  191.                     args[i] = args[i + 1];
  192.                     args[i + 1] = NULL;
  193.                 }
  194.             continue;
  195.         }
  196.         for (int i = 0; i < lsh_num_builtins(); i++)
  197.             if (strcmp(args[0], builtin_str[i]) == 0)
  198.                 return (*builtin_func[i])(args);
  199.         if (args[first_position][0] == '>' && args[first_position][1] == '>')
  200.             return lsh_launch(args, first_position); /*Wykryte przekierowanie.*/
  201.         else if (args[first_position][0] == '|')
  202.         { /*Wykryte potoki.*/
  203.             char ***cmd;
  204.             int counter, potoki_count = 0, cmd_position1 = 0, count_arguments = 0;
  205.             for (counter = 0; args[counter] != NULL; counter++)
  206.                 if (args[counter][0] == '|')
  207.                     potoki_count++;
  208.             cmd = (char ***)malloc((potoki_count + 1) * sizeof(char **));
  209.             for (counter = 0; args[counter] != NULL; counter++)
  210.             { /*Przygotowanie poleceń do przekazania.*/
  211.                 if (args[counter][0] == '|')
  212.                 {
  213.                     cmd[cmd_position1] = (char **)malloc((count_arguments + 1) * sizeof(char *));
  214.                     for (int i = 0; i < count_arguments; i++)
  215.                         cmd[cmd_position1][i] = args[counter - count_arguments + i];
  216.                     cmd[cmd_position1][count_arguments] = NULL;
  217.                     cmd_position1++;
  218.                     count_arguments = 0;
  219.                 }
  220.                 else if (args[counter + 1] == NULL)
  221.                 {
  222.                     cmd[cmd_position1] = (char **)malloc((count_arguments + 2) * sizeof(char *));
  223.                     for (int i = 0; i <= count_arguments + 1; i++)
  224.                         cmd[cmd_position1][i] = args[counter - count_arguments + i];
  225.                     cmd[cmd_position1][count_arguments + 1] = NULL;
  226.                     cmd_position1++;
  227.  
  228.                     count_arguments = 0;
  229.                 }
  230.                 else
  231.                     count_arguments++;
  232.             }
  233.             cmd[cmd_position1] = NULL;
  234.             lsh_loop_pipe(cmd);
  235.             for (int i = 1; i < cmd_position1; i++)
  236.                 free(cmd[i]);
  237.             free(cmd);
  238.             return 1;
  239.         }
  240.     }
  241.     if (args[0] != NULL)
  242.         return lsh_launch(args, -1);
  243.     else
  244.         return 1;
  245. }
  246.  
  247. void lsh_save_line(char *line) /*Funkcja zapisująca podane polecenie do pliku historii.*/
  248. {
  249.     char *path = lsh_get_history_dir();
  250.     FILE *fp;
  251.     char commands[20][254];
  252.     int i = 0;
  253.     size_t len = 0;
  254.     ssize_t read;
  255.     if ((fp = fopen(path, "r")) != NULL)
  256.     {
  257.         while (fgets(commands[i], sizeof(commands[i]), fp)) /*zczytujemy zawartość do tablicy.*/
  258.             i++;
  259.         fclose(fp);
  260.     }
  261.     else
  262.         puts("Nie udalo sie otworzyc pliku.\nPowstanie nowy plik historii.");
  263.  
  264.     if (i < MAX_COMMAND_HISTORY - 1) /*Jeśli ilość poleceń nie przekracza*/
  265.     {                                /*20 dodajemy na koniec pliku.*/
  266.         if ((fp = fopen(path, "a")) != NULL)
  267.         {
  268.             fputs(line, fp);
  269.             fclose(fp);
  270.         }
  271.     }
  272.     else
  273.     {
  274.         if ((fp = fopen(path, "w")) != NULL) /*W przeciwnym wypadku pomijamy najstarszą*/
  275.         {                                    /*komendę i dodajemy na koneic nowa.*/
  276.             for (int j = 1; j < i; j++)
  277.                 fputs(commands[j], fp);
  278.             fputs(line, fp);
  279.             fclose(fp);
  280.         }
  281.     }
  282. }
  283.  
  284. char *lsh_read_line(void) /*Zczytuje wpisane polecenie do tablicy charów.*/
  285. {
  286.     char *line = NULL;
  287.     ssize_t bufsize = 0;
  288.     getline(&line, &bufsize, stdin);
  289.     return line;
  290. }
  291.  
  292. char **lsh_split_line(char *line) /*Funkcja rozdzielająca ciąg poleceń do tablicy.*/
  293. {
  294.     int bufsize = LSH_TOK_BUFSIZE, position = 0;
  295.     char **args = malloc(bufsize * sizeof(char *)), *arg;
  296.     if (!args)
  297.     {
  298.         fprintf(stderr, "lsh: allocation error\n");
  299.         exit(EXIT_FAILURE);
  300.     }
  301.     lsh_save_line(line); /*Wywołanie funkcji zapisującej polecenia w historii.*/
  302.     arg = strtok(line, LSH_TOK_DELIM);
  303.     while (arg != NULL)
  304.     {
  305.         args[position] = arg;
  306.         position++;
  307.         if (position >= bufsize)
  308.         {
  309.             bufsize += LSH_TOK_BUFSIZE;
  310.             args = realloc(args, bufsize * sizeof(char *));
  311.             if (!args)
  312.             {
  313.                 fprintf(stderr, "lsh: allocation error\n");
  314.                 exit(EXIT_FAILURE);
  315.             }
  316.         }
  317.         arg = strtok(NULL, LSH_TOK_DELIM);
  318.     }
  319.     args[position] = NULL;
  320.     return args;
  321. }
  322.  
  323. void lsh_loop() /*Głowna pętla shella.*/
  324. {
  325.     char *line;
  326.     char **args;
  327.     int status;
  328.     do
  329.     {
  330.         printf("> ");
  331.         line = lsh_read_line();
  332.         args = lsh_split_line(line);
  333.         if (args[0] == NULL)
  334.             continue;
  335.         status = lsh_execute(args);
  336.         free(line);
  337.         free(args);
  338.     } while (status);
  339. }
  340.  
  341. int main(int argc, char **argv)
  342. {
  343.     lsh_loop();
  344.     return EXIT_SUCCESS;
  345. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top