mirror of
				https://gitlab.com/klmp200/fish.git
				synced 2025-10-31 17:23:04 +00:00 
			
		
		
		
	Merge branch 'sli' into 'master'
On a des grosses bites See merge request !15
This commit is contained in:
		| @@ -10,6 +10,7 @@ | ||||
|  | ||||
| /* Necessary global variables */ | ||||
| char * builtinCommandsStr[] = { | ||||
| 		(char *) "clear", | ||||
| 		(char *) "kek", | ||||
| 		(char *) "cd", | ||||
| 		(char *) "help", | ||||
| @@ -17,6 +18,7 @@ char * builtinCommandsStr[] = { | ||||
| }; | ||||
|  | ||||
| builtinCommand *builtinCommands[] = { | ||||
| 		&fishClear, | ||||
| 		&fishKek, | ||||
| 		&fishCd, | ||||
| 		&fishHelp, | ||||
| @@ -81,3 +83,16 @@ int fishKek(WordArray *args) { | ||||
| int getNbBuiltins() { | ||||
| 	return sizeof(builtinCommandsStr) / sizeof(char*); | ||||
| } | ||||
|  | ||||
| void fishSignalHandler(int s) { | ||||
| 	switch (s) { | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int fishClear(WordArray *args) { | ||||
| 	if (args != NULL) freeWordArray(args); | ||||
| 	system("clear"); | ||||
| 	return EXIT_SUCCESS; | ||||
| } | ||||
|   | ||||
| @@ -23,4 +23,8 @@ int fishExit(WordArray * args); | ||||
|  | ||||
| int fishKek(WordArray *args); | ||||
|  | ||||
| int fishClear(WordArray *args); | ||||
|  | ||||
| void fishSignalHandler(int s); | ||||
|  | ||||
| #endif //FISH_FISH_COMMANDS_H | ||||
|   | ||||
| @@ -1,25 +1,83 @@ | ||||
| // | ||||
| // Created by Antoine Bartuccio on 11/05/2017. | ||||
| // Dont forget that Antoine Bartuccio is a faggot since 1784 (tm) | ||||
| // | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/wait.h> | ||||
| #include <signal.h> | ||||
| #include <pcre.h> | ||||
| #include "fish_core.h" | ||||
| #include "fish_globbing.h" | ||||
| #include "fish_types.h" | ||||
|  | ||||
| #define REDIRECT_EXIT_FREE() signal = EXIT_FAILURE; \ | ||||
| 	freeWordList(list);\ | ||||
| 	freeWordList(splited); | ||||
|  | ||||
| #define REDIRECT_STD(std, open_mode) if (splited->size == 0) {REDIRECT_EXIT_FREE()\ | ||||
|     } else {\ | ||||
| 		redirect_file = fopen(splited->first->word, open_mode);\ | ||||
| 		if (redirect_file == NULL) { REDIRECT_EXIT_FREE() } else {\ | ||||
| 			saved_std = dup(std);\ | ||||
| 			dup2(fileno(redirect_file), std);\ | ||||
| 			signal = fishExecute(list);\ | ||||
| 			dup2(saved_std, std);\ | ||||
| 			fclose(redirect_file);\ | ||||
| 			freeWordList(splited);\ | ||||
| 		}\ | ||||
| 	} | ||||
|  | ||||
| pipe_redirection * getRedirection(){ | ||||
| 	static pipe_redirection * redirection = NULL; | ||||
|  | ||||
| 	if (redirection == NULL){ | ||||
| 		redirection = (pipe_redirection*) malloc(sizeof(pipe_redirection)); | ||||
| 		if (redirection == NULL) crash(); | ||||
| 		redirection->files_name[0] = strdup((char*) "/tmp/fishXXXXXX"); | ||||
| 		redirection->files_name[1] = strdup((char*) "/tmp/fishXXXXXX"); | ||||
| 		redirection->tmp_files[0] = mkstemp(redirection->files_name[0]); | ||||
| 		redirection->tmp_files[1] = mkstemp(redirection->files_name[1]); | ||||
| 		redirection->to_use = 0; | ||||
| 		redirection->read = WRITE; | ||||
| 		redirection->nb = 0; | ||||
| 		redirection->nb_max = 0; | ||||
| 		redirection->file_use = 0; | ||||
| 	} | ||||
|  | ||||
| 	return redirection; | ||||
|  | ||||
| } | ||||
|  | ||||
| void freeRedirection(){ | ||||
| 	pipe_redirection * redirection = getRedirection(); | ||||
| 	close(redirection->tmp_files[0]); | ||||
| 	close(redirection->tmp_files[1]); | ||||
| 	unlink(redirection->files_name[0]); | ||||
| 	unlink(redirection->files_name[1]); | ||||
| 	remove(redirection->files_name[0]); | ||||
| 	remove(redirection->files_name[1]); | ||||
| 	free(redirection->files_name[0]); | ||||
| 	free(redirection->files_name[1]); | ||||
| 	free(redirection); | ||||
| } | ||||
|  | ||||
|  | ||||
| void fishLoop(Settings * settings){ | ||||
| 	char * line = NULL; | ||||
| 	WordList* splited = NULL; | ||||
| 	int status = 1; | ||||
| 	pipe_redirection *r = getRedirection(); | ||||
|  | ||||
|     do { | ||||
|         printf("%s", settings->PS1); | ||||
|         line = fishReadLine(); | ||||
|  | ||||
| 		r->to_use = 0; | ||||
| 		r->nb = countSeparators(line, (char*) "\\|[^\\|]"); | ||||
| 		r->nb_max = r->nb; | ||||
| 		splited = split(line, (char*) FISH_TOKENS); | ||||
| 		splited = fishExpand(splited); | ||||
|  | ||||
| @@ -30,20 +88,24 @@ void fishLoop(Settings * settings){ | ||||
| 	} while(status != EXIT_SIGNAL); | ||||
| } | ||||
|  | ||||
| int countSeparators(char *string, char *separators) { | ||||
| int countSeparators(char *string, char *regex) { | ||||
| 	const char* error; | ||||
| 	int error_offset; | ||||
| 	int ovector[100]; | ||||
| 	int nb = 0; | ||||
| 	int i = 0; | ||||
| 	int k = 0; | ||||
| 	while (string[i] != '\0'){ | ||||
| 		while (separators[k] != '\0'){ | ||||
| 			if (string[i] == separators[k]){ | ||||
| 				nb++; | ||||
| 			} | ||||
| 			k++; | ||||
| 		} | ||||
| 		i++; | ||||
| 		k = 0; | ||||
| 	int string_size = (int) strlen(string); | ||||
| 	int ovector_size = 100; | ||||
| 	int offset = 0; | ||||
| 	pcre *re = pcre_compile(regex, 0, &error, &error_offset, 0); | ||||
|  | ||||
| 	if (!re) crash(); | ||||
|  | ||||
| 	while (pcre_exec(re, 0, string, string_size, offset, 0, ovector, ovector_size) >= 0){ | ||||
| 		offset = ovector[1]; | ||||
| 		nb++; | ||||
| 	} | ||||
| 	pcre_free(re); | ||||
|  | ||||
| 	return nb; | ||||
| } | ||||
|  | ||||
| @@ -66,24 +128,26 @@ WordList * split(char *string, char *separator){ | ||||
| } | ||||
|  | ||||
| char *fishReadLine() { | ||||
| 	struct sigaction signal_handler; | ||||
| 	size_t bufferSize = FISH_BUFFER_SIZE; | ||||
| 	int position = 0; | ||||
| 	char *line = (char*) malloc(sizeof(char*) * bufferSize); | ||||
| 	int c; | ||||
|  | ||||
| 	if (line == NULL){ | ||||
| 		crash(); | ||||
| 	} | ||||
| 	if (line == NULL) crash(); | ||||
|  | ||||
| 	signal_handler.sa_handler = fishSignalHandler; | ||||
| 	sigemptyset(&signal_handler.sa_mask); | ||||
| 	signal_handler.sa_flags = 0; | ||||
|  | ||||
| 	while (1){ | ||||
| 		sigaction(SIGINT, &signal_handler, NULL); | ||||
| 		c = getchar(); | ||||
|  | ||||
| 		switch (c){ | ||||
| 			case '\n': | ||||
| 				line[position] = '\0'; | ||||
| 				return line; | ||||
| 			case EOF: | ||||
| 				exit(EXIT_SUCCESS); | ||||
| 			default: | ||||
| 				line[position] = (char) c; | ||||
| 		} | ||||
| @@ -91,7 +155,7 @@ char *fishReadLine() { | ||||
| 		position++; | ||||
|  | ||||
| 		if ((size_t) position > bufferSize){ | ||||
| 			bufferSize+=bufferSize; | ||||
| 			bufferSize += bufferSize; | ||||
| 			line = (char*) realloc(line, bufferSize); | ||||
| 			if (line == NULL){ | ||||
| 				crash(); | ||||
| @@ -99,7 +163,6 @@ char *fishReadLine() { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| @@ -107,9 +170,20 @@ char *fishReadLine() { | ||||
| int fishLoad(WordArray *array) { | ||||
| 	pid_t pid; | ||||
| 	int status = 1; | ||||
| 	pipe_redirection *redirection = getRedirection(); | ||||
|  | ||||
| 	pid = fork(); | ||||
| 	if (pid == 0){ | ||||
| 		if (redirection->to_use){ | ||||
| 			if (redirection->read == READ){ | ||||
| 				dup2(redirection->tmp_files[redirection->file_use], STDIN_FILENO); | ||||
| 			} else if (redirection->read == WRITE) { | ||||
| 				dup2(redirection->tmp_files[redirection->file_use], STDOUT_FILENO); | ||||
| 			} else { | ||||
| 				dup2(redirection->tmp_files[!redirection->file_use], STDIN_FILENO); | ||||
| 				dup2(redirection->tmp_files[redirection->file_use], STDOUT_FILENO); | ||||
| 			} | ||||
| 		} | ||||
| 		/* Executes only in the child process */ | ||||
| 		if (execvp(array->words[0], array->words) == -1){ | ||||
| 			/* Error during system call */ | ||||
| @@ -121,7 +195,6 @@ int fishLoad(WordArray *array) { | ||||
| 		perror("fish"); | ||||
| 	} else { | ||||
| 		/* Handle parent process */ | ||||
|  | ||||
| 		/* Wait for the child process to finish */ | ||||
| 		do { | ||||
| 			waitpid(pid, &status, WUNTRACED); | ||||
| @@ -129,6 +202,7 @@ int fishLoad(WordArray *array) { | ||||
| 		if (status) fprintf(stderr, "%s\n", getInsult()); | ||||
| 	} | ||||
| 	freeWordArray(array); | ||||
|  | ||||
| 	return status; | ||||
| } | ||||
|  | ||||
| @@ -136,6 +210,10 @@ int fishExecute(WordList *list) { | ||||
| 	WordList *splited = NULL; | ||||
| 	shell_operator op = NONE; | ||||
| 	WordArray *array = NULL; | ||||
| 	pipe_redirection *redirection = NULL; | ||||
| 	FILE *redirect_file = NULL; | ||||
| 	int saved_std; | ||||
| 	int pid; | ||||
| 	int signal = 1; | ||||
|  | ||||
| 	splited = parseWordList(list, &op); | ||||
| @@ -160,6 +238,71 @@ int fishExecute(WordList *list) { | ||||
| 			signal = fishExecute(list); | ||||
| 			if (signal != EXIT_SIGNAL) signal = fishExecute(splited); | ||||
| 			break; | ||||
| 		case PIPE: | ||||
| 			redirection = getRedirection(); | ||||
|  | ||||
| 			if (redirection->nb == redirection->nb_max){ | ||||
| 				redirection->read = WRITE; | ||||
| 				redirection->file_use = 0; | ||||
| 			} else if (redirection->nb > 0){ | ||||
| 				redirection->read = READ_AND_WRITE; | ||||
| 				redirection->file_use = !redirection->file_use; | ||||
| 			} else { | ||||
| 				redirection->read = READ; | ||||
| 				redirection->file_use = !redirection->file_use; | ||||
| 			} | ||||
| 			redirection->to_use = 1; | ||||
| 			--redirection->nb; | ||||
|  | ||||
| 			if (redirection->read == WRITE) ftruncate(redirection->tmp_files[redirection->file_use], 0); | ||||
| 			lseek(redirection->tmp_files[0], 0L, 0); | ||||
| 			lseek(redirection->tmp_files[1], 0L, 0); | ||||
|  | ||||
| 			fishExecute(list); | ||||
|  | ||||
| 			redirection->read = WRITE; | ||||
| 			if (redirection->nb > 0){ | ||||
| 				redirection->read = READ_AND_WRITE; | ||||
| 			} else { | ||||
| 				redirection->read = READ; | ||||
| 			} | ||||
| 			if (redirection->read == WRITE) ftruncate(redirection->tmp_files[redirection->file_use], 0); | ||||
| 			lseek(redirection->tmp_files[0], 0L, 0); | ||||
| 			lseek(redirection->tmp_files[1], 0L, 0); | ||||
|  | ||||
| 			signal = fishExecute(splited); | ||||
|  | ||||
| 			redirection->to_use = 0; | ||||
| 			break; | ||||
| 		case BACKGROUND_PROCESS: | ||||
| 			printf("Exécution en tache de fond\n"); | ||||
| 			pid = fork(); | ||||
| 			if(pid == 0){ | ||||
| 				exit(fishExecute(list)); | ||||
| 			} else if (pid < 0){ | ||||
| 				perror("fish"); | ||||
| 			} else if (splited->size > 0) signal = fishExecute(splited); | ||||
| 			else { | ||||
| 				freeWordList(splited); | ||||
| 				splited = NULL; | ||||
| 				signal = EXIT_SUCCESS; | ||||
| 			} | ||||
| 			break; | ||||
| 		case REDIRECT_STDOUT_ERASE: | ||||
| 			REDIRECT_STD(STDOUT_FILENO, "w"); | ||||
| 			break; | ||||
| 		case REDIRECT_STDOUT_APPEND: | ||||
| 			REDIRECT_STD(STDOUT_FILENO, "a"); | ||||
| 			break; | ||||
| 		case REDIRECT_STDERR_ERASE: | ||||
| 			REDIRECT_STD(STDERR_FILENO, "w"); | ||||
| 			break; | ||||
| 		case REDIRECT_STDERR_APPEND: | ||||
| 			REDIRECT_STD(STDERR_FILENO, "a"); | ||||
| 			break; | ||||
| 		case REDIRECT_STDIN: | ||||
| 			REDIRECT_STD(STDIN_FILENO, "r"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			array = wordListToWordArray(list); | ||||
| 			signal = loadRightCommand(array); | ||||
| @@ -197,12 +340,26 @@ WordList * parseWordList(WordList *list, shell_operator *an_operator) { | ||||
| 	char *op_str[] = { | ||||
| 			(char*) ";", | ||||
| 			(char*) "\\|\\|", | ||||
| 			(char*) "&&" | ||||
| 			(char*) "&&", | ||||
| 			(char*) "\\|", | ||||
| 			(char*) "&", | ||||
| 			(char*) "2>>", | ||||
| 			(char*) ">>", | ||||
| 			(char*) "2>", | ||||
| 			(char*) ">", | ||||
| 			(char*) "<[^<]" | ||||
| 	}; | ||||
| 	shell_operator op[] = { | ||||
| 			OR, | ||||
| 			REVERSE_AND, | ||||
| 			AND | ||||
| 			AND, | ||||
| 			PIPE, | ||||
| 			BACKGROUND_PROCESS, | ||||
| 			REDIRECT_STDERR_APPEND, | ||||
| 			REDIRECT_STDOUT_APPEND, | ||||
| 			REDIRECT_STDERR_ERASE, | ||||
| 			REDIRECT_STDOUT_ERASE, | ||||
| 			REDIRECT_STDIN | ||||
| 	}; | ||||
| 	WordList *newList = NULL; | ||||
| 	int max = sizeof(op_str) / sizeof(char*); | ||||
|   | ||||
| @@ -27,7 +27,7 @@ void fishLoop(Settings * settings); | ||||
|  | ||||
| char * fishReadLine(); | ||||
|  | ||||
| int countSeparators(char *string, char *separators); // Tested | ||||
| int countSeparators(char *string, char *regex); // Tested | ||||
|  | ||||
| int fishLoad(WordArray *array); | ||||
|  | ||||
| @@ -37,4 +37,12 @@ WordList *parseWordList(WordList *list, shell_operator *an_operator); | ||||
|  | ||||
| int loadRightCommand(WordArray *array); | ||||
|  | ||||
| /* IN/OUT functions */ | ||||
|  | ||||
| /* Get a global pipe_redirection structure */ | ||||
| pipe_redirection * getRedirection(); | ||||
|  | ||||
| /* Free redirection structure DO NOT TRY TO GET REDIRECTION AFTER */ | ||||
| void freeRedirection(); | ||||
|  | ||||
| #endif //FISH_FISH_CORE_H | ||||
|   | ||||
| @@ -20,9 +20,20 @@ typedef enum { | ||||
| 	BACKGROUND_PROCESS, | ||||
| 	AND, | ||||
| 	OR, | ||||
| 	REVERSE_AND | ||||
| 	REVERSE_AND, | ||||
| 	REDIRECT_STDOUT_ERASE, | ||||
| 	REDIRECT_STDOUT_APPEND, | ||||
| 	REDIRECT_STDERR_ERASE, | ||||
| 	REDIRECT_STDERR_APPEND, | ||||
| 	REDIRECT_STDIN | ||||
| } shell_operator ; | ||||
|  | ||||
| typedef enum { | ||||
| 	READ, | ||||
| 	WRITE, | ||||
| 	READ_AND_WRITE | ||||
| } redirection_mode ; | ||||
|  | ||||
| typedef struct { | ||||
| 	char ** words; | ||||
| 	int size; | ||||
| @@ -47,6 +58,15 @@ typedef struct { | ||||
| 	struct passwd* passwd; | ||||
| } Settings; | ||||
|  | ||||
| typedef struct { | ||||
| 	int to_use; | ||||
| 	int nb; | ||||
| 	int nb_max; | ||||
| 	int file_use; | ||||
| 	int tmp_files[2]; | ||||
| 	char * files_name[2]; | ||||
| 	redirection_mode read; | ||||
| } pipe_redirection; | ||||
|  | ||||
| typedef int (builtinCommand) (WordArray*); | ||||
|  | ||||
|   | ||||
| @@ -29,5 +29,8 @@ TEST(command_split, split){ | ||||
| } | ||||
|  | ||||
| TEST(count_tokens, countSeparators){ | ||||
| 	ASSERT_TRUE(countSeparators((char*) "Ceci est un super \n test", (char*) FISH_TOKENS) == 6); | ||||
| 	ASSERT_TRUE(countSeparators((char*) "Ceci est un super \n test", (char*) " ") == 5); | ||||
| 	ASSERT_TRUE(countSeparators((char*) "patate | patate| patatine", (char*) "\\|") == 2); | ||||
| 	ASSERT_TRUE(countSeparators((char*) "patate | patate| patatine |", (char*) "\\|") == 3); | ||||
| 	ASSERT_TRUE(countSeparators((char*) "patate | patate|| patatine |", (char*) "\\|[^\\|]") == 2); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user