Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <sys/wait.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
- #include <signal.h>
- #define LSH_TOK_BUFSIZE 64
- #define LSH_TOK_DELIM " \t\r\n\a"
- #define MAX_COMMAND_HISTORY 20
- int lsh_cd(char **args);
- int lsh_help(char **args);
- int lsh_exit(char **args);
- char *builtin_str[] = {
- "cd",
- "help",
- "exit" };
- int(*builtin_func[])(char **) = {
- &lsh_cd,
- &lsh_help,
- &lsh_exit,
- };
- int lsh_num_builtins() /*Funkcja zwraca ilość wbudowanych poleceń.*/
- {
- return sizeof(builtin_str) / sizeof(char *);
- }
- char *lsh_get_history_dir(void) /*Zwraca ścieżkę do pliku z historią poleceń*/
- {
- char filepath[] = "bash_history.txt";
- char *homedir = getenv("HOME");
- char *path = malloc((strlen(filepath) + strlen(homedir) + 1) * sizeof(char));
- strcpy(path, homedir);
- strcat(path, "/");
- strcat(path, filepath);
- return path;
- }
- int lsh_cd(char **args) /*Obsługa polecenia cd.*/
- {
- if (args[1] == NULL)
- fprintf(stderr, "lsh: expected argument to \"cd\"\n");
- else if (chdir(args[1]) != 0)
- perror("lsh");
- return 1;
- }
- int lsh_help(char **args) /*Obsługa polecenia help.*/
- {
- puts("Dostepne komendy: \n");
- for (int i = 0; i < lsh_num_builtins(); i++)
- printf(" %s\n", builtin_str[i]);
- printf(" history\n");
- puts("Program przygotowany na zajecia z Systemow Operacyjnych przez:");
- puts("Emilie Jutkiewicz\nDawida Rydzewskiego\nRadoslawa Skiepko");
- return 1;
- }
- void lsh_history(int sig) /*Obsługa polecenia history.*/
- {
- if (sig == SIGUSR1) //Funkcję wywołuje sygnał SIGUSR1, funkcja jest 'handlerem' tego sygnału.
- {
- puts("");
- int f = open(lsh_get_history_dir(), O_RDONLY);
- if (f != -1)
- {
- char buf[100];
- while (read(f, buf, 100))
- write(1, buf, strlen(buf));
- puts("");
- close(f);
- }
- }
- }
- int lsh_exit(char **args) /*Obsługa polecenia exit.*/
- {
- return 0;
- }
- int lsh_launch(char **args, int flag) /*Funkcja uruchamiająca polecenia.*/
- {
- pid_t pid, wpid;
- int status, background_flag = 0, position = 0, position2 = 0;
- pid = fork();
- while (args[position] != NULL)
- position++;
- /* Pętla sprawdza czy wystąpiło żadąnie działania w tle.*/
- while (args[position - 1][position2] != '\0')
- position2++;
- if (args[position - 1][position2 - 1] == '&')
- {
- background_flag = 1; /*Jeśli wytąpiło zmienia flagę działania w tle.*/
- args[position - 1][position2 - 1] = '\0';
- }
- if (pid == 0)
- {
- if (flag != -1) /*Jeśli w poleceniu wystąpiło przekierowanie ">>", zmienna*/
- { /*flag przyjmuje wartość w którym nastąpiło.*/
- int fd1;
- if ((fd1 = open(args[flag + 1], O_WRONLY | O_CREAT | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
- {
- perror(args[flag + 1]);
- exit(EXIT_FAILURE);
- }
- dup2(fd1, 1); /*Zmiana standardowego wyjścia na przekazane po znakach ">>".*/
- close(fd1);
- args[flag] = args[flag + 1] = NULL; /*Usunięcie z tablicy poleceń przekierowania.*/
- }
- if (execvp(args[0], args) == -1) /*Uruchamianie poleceń, w przypadku błędu wyświetla error.*/
- perror("lsh");
- exit(EXIT_FAILURE);
- }
- else if (pid < 0)
- perror("lsh");
- else if (background_flag == 0) /*Gdy wystąpiło żądanie działania w tle program nie wchodzi*/
- do /*w pętle i nie czeka na zakończenie uruchomionego procesu.*/
- {
- wpid = waitpid(pid, &status, WUNTRACED);
- } while (!WIFEXITED(status) && !WIFSIGNALED(status));
- return 1;
- }
- int lsh_loop_pipe(char ***cmd) /*Pętla wykonująca nielimitowane potoki*/
- {
- int p[2];
- pid_t pid, wpid;
- int status;
- int fd_in = 0;
- while (*cmd != NULL)
- {
- pipe(p);
- pid = fork();
- if (pid == 0)
- {
- dup2(fd_in, 0); /*Zmiana wejścia zgodnie z starszym*/
- if (*(cmd + 1) != NULL)
- dup2(p[1], 1);
- close(p[0]);
- execvp((*cmd)[0], *cmd); /*Wykonanie polecenia*/
- exit(EXIT_FAILURE);
- }
- else if (pid < 0)
- {
- perror("lsh");
- }
- else
- {
- do
- {
- wpid = waitpid(pid, &status, WUNTRACED);
- } while (!WIFEXITED(status) && !WIFSIGNALED(status));
- close(p[1]);
- fd_in = p[0]; /*Zapisanie wejścia dla następnej komendy*/
- cmd++;
- }
- }
- }
- int lsh_execute(char **args) /*Funkcja sprawdza czy wystąpiły predefiniowane polecenia,*/
- { /*przekierowania lub potoki.*/
- int second_position, history_flag, output_flag;
- char tmp_history[] = "history";
- for (int first_position = 0; args[first_position] != NULL; first_position++)
- { /*Pętla przechodząca po wszystkich argumentach.*/
- history_flag = 1;
- output_flag = 0;
- for (second_position = 0; second_position < 7; second_position++)
- if (args[first_position][second_position] != tmp_history[second_position])
- { /*Sprawdza czy wystąpiło polecenie history.*/
- history_flag = 0;
- break;
- }
- if (history_flag == 1)
- {
- if (signal(SIGUSR1, lsh_history) == SIG_ERR) /*Definiowanie obsługi sygnału.*/
- printf("Nie udalo sie obsluzyc sygnalu");
- raise(SIGUSR1); /*Wywołanie wyświetlenia historii poleceń.*/
- if (args[first_position + 1] == NULL)
- args[first_position] = NULL;
- else
- for (int i = first_position; args[i + 1] != NULL; i++)
- {
- args[i] = args[i + 1];
- args[i + 1] = NULL;
- }
- continue;
- }
- for (int i = 0; i < lsh_num_builtins(); i++)
- if (strcmp(args[0], builtin_str[i]) == 0)
- return (*builtin_func[i])(args);
- if (args[first_position][0] == '>' && args[first_position][1] == '>')
- return lsh_launch(args, first_position); /*Wykryte przekierowanie.*/
- else if (args[first_position][0] == '|')
- { /*Wykryte potoki.*/
- char ***cmd;
- int counter, potoki_count = 0, cmd_position1 = 0, count_arguments = 0;
- for (counter = 0; args[counter] != NULL; counter++)
- if (args[counter][0] == '|')
- potoki_count++;
- cmd = (char ***)malloc((potoki_count + 1) * sizeof(char **));
- for (counter = 0; args[counter] != NULL; counter++)
- { /*Przygotowanie poleceń do przekazania.*/
- if (args[counter][0] == '|')
- {
- cmd[cmd_position1] = (char **)malloc((count_arguments + 1) * sizeof(char *));
- for (int i = 0; i < count_arguments; i++)
- cmd[cmd_position1][i] = args[counter - count_arguments + i];
- cmd[cmd_position1][count_arguments] = NULL;
- cmd_position1++;
- count_arguments = 0;
- }
- else if (args[counter + 1] == NULL)
- {
- cmd[cmd_position1] = (char **)malloc((count_arguments + 2) * sizeof(char *));
- for (int i = 0; i <= count_arguments + 1; i++)
- cmd[cmd_position1][i] = args[counter - count_arguments + i];
- cmd[cmd_position1][count_arguments + 1] = NULL;
- cmd_position1++;
- count_arguments = 0;
- }
- else
- count_arguments++;
- }
- cmd[cmd_position1] = NULL;
- lsh_loop_pipe(cmd);
- for (int i = 1; i < cmd_position1; i++)
- free(cmd[i]);
- free(cmd);
- return 1;
- }
- }
- if (args[0] != NULL)
- return lsh_launch(args, -1);
- else
- return 1;
- }
- void lsh_save_line(char *line) /*Funkcja zapisująca podane polecenie do pliku historii.*/
- {
- char *path = lsh_get_history_dir();
- FILE *fp;
- char commands[20][254];
- int i = 0;
- size_t len = 0;
- ssize_t read;
- if ((fp = fopen(path, "r")) != NULL)
- {
- while (fgets(commands[i], sizeof(commands[i]), fp)) /*zczytujemy zawartość do tablicy.*/
- i++;
- fclose(fp);
- }
- else
- puts("Nie udalo sie otworzyc pliku.\nPowstanie nowy plik historii.");
- if (i < MAX_COMMAND_HISTORY - 1) /*Jeśli ilość poleceń nie przekracza*/
- { /*20 dodajemy na koniec pliku.*/
- if ((fp = fopen(path, "a")) != NULL)
- {
- fputs(line, fp);
- fclose(fp);
- }
- }
- else
- {
- if ((fp = fopen(path, "w")) != NULL) /*W przeciwnym wypadku pomijamy najstarszą*/
- { /*komendę i dodajemy na koneic nowa.*/
- for (int j = 1; j < i; j++)
- fputs(commands[j], fp);
- fputs(line, fp);
- fclose(fp);
- }
- }
- }
- char *lsh_read_line(void) /*Zczytuje wpisane polecenie do tablicy charów.*/
- {
- char *line = NULL;
- ssize_t bufsize = 0;
- getline(&line, &bufsize, stdin);
- return line;
- }
- char **lsh_split_line(char *line) /*Funkcja rozdzielająca ciąg poleceń do tablicy.*/
- {
- int bufsize = LSH_TOK_BUFSIZE, position = 0;
- char **args = malloc(bufsize * sizeof(char *)), *arg;
- if (!args)
- {
- fprintf(stderr, "lsh: allocation error\n");
- exit(EXIT_FAILURE);
- }
- lsh_save_line(line); /*Wywołanie funkcji zapisującej polecenia w historii.*/
- arg = strtok(line, LSH_TOK_DELIM);
- while (arg != NULL)
- {
- args[position] = arg;
- position++;
- if (position >= bufsize)
- {
- bufsize += LSH_TOK_BUFSIZE;
- args = realloc(args, bufsize * sizeof(char *));
- if (!args)
- {
- fprintf(stderr, "lsh: allocation error\n");
- exit(EXIT_FAILURE);
- }
- }
- arg = strtok(NULL, LSH_TOK_DELIM);
- }
- args[position] = NULL;
- return args;
- }
- void lsh_loop() /*Głowna pętla shella.*/
- {
- char *line;
- char **args;
- int status;
- do
- {
- printf("> ");
- line = lsh_read_line();
- args = lsh_split_line(line);
- if (args[0] == NULL)
- continue;
- status = lsh_execute(args);
- free(line);
- free(args);
- } while (status);
- }
- int main(int argc, char **argv)
- {
- lsh_loop();
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement