├── .github └── workflows │ └── sync-to-gitlab.yml ├── .gitignore ├── README.md ├── doc ├── Chapter5-WritingYourOwnShell.pdf ├── EQ04If9XYAAaGJK.jpeg ├── Subject │ └── en.subject.pdf ├── book-rev7.pdf ├── test │ └── main.c └── witeboard_cfc66f20-d1b8-11ee-8005-578a88b9ab70.png ├── generate_ast_diagram └── generate_ast_diagram.c └── minishell ├── Makefile ├── includes └── minishell.h ├── lib └── libft │ ├── Makefile │ ├── ft_atoi.c │ ├── ft_bzero.c │ ├── ft_calloc.c │ ├── ft_isalnum.c │ ├── ft_isalpha.c │ ├── ft_isascii.c │ ├── ft_isdigit.c │ ├── ft_isprint.c │ ├── ft_isspace.c │ ├── ft_itoa.c │ ├── ft_lstadd_back.c │ ├── ft_lstadd_front.c │ ├── ft_lstclear.c │ ├── ft_lstdelone.c │ ├── ft_lstiter.c │ ├── ft_lstlast.c │ ├── ft_lstnew.c │ ├── ft_lstsize.c │ ├── ft_memchr.c │ ├── ft_memcmp.c │ ├── ft_memcpy.c │ ├── ft_memmove.c │ ├── ft_memset.c │ ├── ft_putchar_fd.c │ ├── ft_putendl_fd.c │ ├── ft_putnbr_fd.c │ ├── ft_putstr_fd.c │ ├── ft_split.c │ ├── ft_strchr.c │ ├── ft_strdup.c │ ├── ft_striteri.c │ ├── ft_strjoin.c │ ├── ft_strlcat.c │ ├── ft_strlcpy.c │ ├── ft_strlen.c │ ├── ft_strmapi.c │ ├── ft_strncmp.c │ ├── ft_strndup.c │ ├── ft_strnlen.c │ ├── ft_strnstr.c │ ├── ft_strrchr.c │ ├── ft_strtrim.c │ ├── ft_substr.c │ ├── ft_tolower.c │ ├── ft_toupper.c │ └── libft.h └── src ├── 01_input_validation ├── syntax_checker.c └── syntax_checker_utils.c ├── 02_tokenization ├── print_tokens.c ├── tokenizer.c └── tokenizer_utils.c ├── 03_parsing ├── parser.c └── parser_utils.c ├── 04_execution ├── builtin_command_execution.c ├── builtin_command_execution2.c ├── command_execution_adv.c ├── command_execution_control.c ├── command_input_preprocessing.c ├── executor.c ├── heredoc_handling.c ├── initialization │ ├── command_execution_init.c │ └── environment_init.c ├── path_utilities.c ├── path_utilities2.c └── process_pipeline_management.c ├── 05_builtin ├── builtin_commands.c ├── builtin_commands_utils.c ├── builtin_commands_utils2.c └── builtin_commands_utils3.c ├── 06_signals └── signal_handlers.c ├── 07_env_var_expansion ├── env_handling.c ├── env_managment.c ├── env_managment2.c ├── variable_expansion.c └── variable_expansion_utils.c ├── main.c └── utils ├── shell_utilities.c └── string_utilities ├── string_utils.c └── string_utils2.c /.github/workflows/sync-to-gitlab.yml: -------------------------------------------------------------------------------- 1 | name: Backup to GitLab 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | schedule: 9 | - cron: "0 2 * * *" 10 | 11 | jobs: 12 | backup: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Setup GitLab Backup 21 | env: 22 | GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }} 23 | GITLAB_URL: ${{ secrets.GITLAB_URL }} 24 | GITLAB_NAMESPACE: ${{ secrets.GITLAB_NAMESPACE }} 25 | run: | 26 | # Configure git 27 | git config --global user.name "github-actions[bot]" 28 | git config --global user.email "github-actions[bot]@users.noreply.github.com" 29 | 30 | # Extract repository name 31 | REPO_NAME=${GITHUB_REPOSITORY#*/} 32 | 33 | # Function to get project ID 34 | get_project_id() { 35 | curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 36 | "https://${GITLAB_URL}/api/v4/projects/${GITLAB_NAMESPACE}%2F${REPO_NAME}" | \ 37 | jq -r '.id' 38 | } 39 | 40 | # Function to configure project settings 41 | configure_project() { 42 | local project_id=$1 43 | echo "Configuring project settings..." 44 | 45 | # Configure project settings 46 | curl -s --request PUT \ 47 | --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 48 | --header "Content-Type: application/json" \ 49 | --data '{ 50 | "only_allow_merge_if_pipeline_succeeds": false, 51 | "allow_merge_on_skipped_pipeline": true, 52 | "restrict_user_defined_variables": false 53 | }' \ 54 | "https://${GITLAB_URL}/api/v4/projects/${project_id}" 55 | 56 | # Remove all existing branch protection 57 | curl -s --request DELETE \ 58 | --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 59 | "https://${GITLAB_URL}/api/v4/projects/${project_id}/protected_branches/main" 60 | 61 | # Add updated branch protection 62 | curl -s --request POST \ 63 | --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 64 | --header "Content-Type: application/json" \ 65 | --data '{ 66 | "name": "main", 67 | "push_access_level": 40, 68 | "merge_access_level": 40, 69 | "unprotect_access_level": 40, 70 | "allow_force_push": true 71 | }' \ 72 | "https://${GITLAB_URL}/api/v4/projects/${project_id}/protected_branches" 73 | } 74 | 75 | # Get or create project 76 | PROJECT_ID=$(get_project_id) 77 | 78 | if [ "$PROJECT_ID" = "null" ] || [ -z "$PROJECT_ID" ]; then 79 | echo "Creating new project..." 80 | curl -s --request POST \ 81 | --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 82 | --header "Content-Type: application/json" \ 83 | --data "{ 84 | \"name\": \"${REPO_NAME}\", 85 | \"path\": \"${REPO_NAME}\", 86 | \"visibility\": \"private\", 87 | \"initialize_with_readme\": false 88 | }" \ 89 | "https://${GITLAB_URL}/api/v4/projects" 90 | 91 | sleep 5 # Wait for project creation 92 | PROJECT_ID=$(get_project_id) 93 | fi 94 | 95 | echo "Project ID: $PROJECT_ID" 96 | 97 | # Configure project settings 98 | configure_project "$PROJECT_ID" 99 | 100 | # Setup and push to GitLab 101 | echo "Setting up Git remote..." 102 | GITLAB_REPO_URL="https://oauth2:${GITLAB_TOKEN}@${GITLAB_URL}/${GITLAB_NAMESPACE}/${REPO_NAME}.git" 103 | git remote add gitlab "$GITLAB_REPO_URL" || git remote set-url gitlab "$GITLAB_REPO_URL" 104 | 105 | echo "Fetching from GitLab..." 106 | git fetch gitlab || true 107 | 108 | echo "Pushing to GitLab..." 109 | # Push all branches except HEAD ref 110 | for branch in $(git branch -r | grep 'origin/' | grep -v 'origin/HEAD'); do 111 | branch_name=${branch#origin/} 112 | git push -f gitlab "$branch:refs/heads/$branch_name" 113 | done 114 | 115 | # Push all tags 116 | git push -f gitlab refs/tags/*:refs/tags/* 117 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | 4 | .DS_Store 5 | minishell/minishell 6 | minishell/ast.dot 7 | ast.dot 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ascii-text-art (3)](https://github.com/zelhajou/42-minishell/assets/39954629/44830c16-9ec2-471f-a075-f6a7e535c0a3) 2 | 3 | 4 | # Minishell 5 | 6 | ## Table of Contents 7 | 8 | 1. [Overview](#overview) 9 | 2. [Project Challenges](#project-challenges) 10 | 3. [Team Development Steps for Minishell](#team-development-steps-for-minishell) 11 | 1. [Initial Planning and Setup](#step-1-initial-planning-and-setup) 12 | 2. [Research and Design Phase](#step-2-research-and-design-phase) 13 | 1. [Shell Operations](#shell-operations) 14 | 2. [External Functions](#external-functions) 15 | 3. [Parsing and Input Management](#step-3-parsing-and-input-management) 16 | 1. [Command Reading](#command-reading) 17 | 2. [Steps for building the parser and AST (Abstract Syntax Tree)](#steps-for-building-the-parser-and-ast-abstract-syntax-tree) 18 | 1. [Designing a Syntax Error Checker](#designing-a-syntax-error-checker) 19 | 2. [Syntax Error Checker Function](#syntax-error-checker-function) 20 | 3. [Tokenization](#tokenization) 21 | 4. [Token Structure](#token-structure) 22 | 5. [Tokenization Strategy](#tokenization-strategy) 23 | 6. [Tokenization Function](#tokenization-function) 24 | 7. [Parsing](#parsing) 25 | 8. [AST Node Structure](#ast-node-structure) 26 | 9. [Parsing Function](#parsing-function) 27 | 10. [AST Visualization](#ast-visualization) 28 | 4. [Command Execution](#step-4-command-execution) 29 | 5. [Built-in Commands Implementation](#step-5-built-in-commands-implementation) 30 | 6. [Signal Handling](#step-6-signal-handling) 31 | 7. [Environment Variable Expansion](#step-7-environment-variable-expansion) 32 | 8. [Testing and Debugging](#step-8-testing-and-debugging) 33 | 4. [Project Structure](#project-structure) 34 | 5. [Team Members](#team-members) 35 | 6. [Resources](#resources) 36 | 7. [Acknowledgements](#acknowledgements) 37 | 38 | 39 | ## Overview 40 | 41 | Our Minishell project represents a collaborative effort to build a custom shell program in C, inspired by the functionalities of [bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)), the Bourne Again SHell. As part of the 42 School curriculum, this project served as a unique opportunity for us to deepen our collective understanding of system processes, file descriptors, and the complexities of command-line interfaces. Through the development of our own shell, we engaged in a comprehensive exploration of Unix-based systems, gaining hands-on experience in process control, command interpretation, and environmental variable management. 42 | 43 | ## Project Challenges 44 | 45 | - **Parsing User Input**: Accurately parsing user input, including handling spaces, quotes, and special characters, while distinguishing between command arguments and options. 46 | - **Executing Commands**: Implementing logic to search for and execute the right executable based on the PATH environment variable or a specified path, and managing execution of built-in commands versus external commands. 47 | - **Signal Handling**: Correctly handling Unix signals such as SIGINT (`ctrl-C`), SIGQUIT (`ctrl-\`), and EOF (`ctrl-D`), and ensuring the shell behaves similarly to bash in response to these signals. 48 | - **Input/Output Redirection and Pipes**: Implementing input and output redirection (`<`, `>`, `>>`, `<<`) and pipes (`|`) to allow for command chaining and data redirection, which involves managing file descriptors and process communication. 49 | - **Environment Variable Expansion**: Managing environment variables and supporting their expansion within commands, including the special case of `$?` to represent the exit status of the most recently executed command. 50 | - **Memory Management**: Ensuring efficient memory management throughout the shell, including preventing memory leaks especially in the context of the readline function and dynamically allocated resources. 51 | - **Built-in Commands Implementation**: Creating internal implementations of several built-in commands (`echo`, `cd`, `pwd`, `export`, `unset`, `env`, `exit`) that behave consistently with their bash counterparts. 52 | - **Concurrency and Process Management**: Handling concurrency through process creation and management, using system calls like `fork`, `execve`, `wait`, and `pipe`, and ensuring robust process control and signal handling. 53 | - **Error Handling**: Developing comprehensive error handling strategies to deal with invalid commands, permissions issues, nonexistent files, and other runtime errors. 54 | 55 | ## Team Development Steps for Minishell 56 | 57 | ### Step 1: Initial Planning and Setup 58 | 59 | - **Repository Setup**: Collaboratively set up the GitHub repository, ensuring a clear directory structure and branch strategy. 60 | - **Makefile Creation**: Makefile that includes rules for `all`, `clean`, `fclean`, `re` 61 | - Set up libft libray 62 | 63 | ### Step 2: Research and Design Phase 64 | 65 | This phase was about understanding the shell's operations, researching the external functions allowed, and dividing them among ourselves to research and explain their usage to the team. 66 | 67 | #### Shell Operations 68 | 69 | ![shell](https://github.com/user-attachments/assets/730358f1-dd34-49f3-b15f-647bef40c40c) 70 | 71 | - [What Happens When You Type a Command in Your Terminal](https://www.youtube.com/watch?v=2P7fcVHxA9o&list=LL&index=6) 📹 72 | - [Shell Code Explained](https://www.youtube.com/playlist?list=PLbtzT1TYeoMhF4hcpEiCsOeN13zqrzBJq) 📹 73 | 74 | - [Shell Command Language](https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html) 📹 75 | 76 | - [Unix terminals and shells](https://www.youtube.com/playlist?list=PLFAC320731F539902) 📹 77 | 78 | - [Terminal vs. Bash vs. Command line vs. Prompt](https://www.youtube.com/watch?v=hMSByvFHOro&ab_channel=LukeSmith) 📹 79 | 80 | ![terminals](https://github.com/user-attachments/assets/0296cfe7-6a1d-42c8-ba4c-53419e64cccd) 81 | 82 | - [Tutorial - Write a Shell in C](https://brennan.io/2015/01/16/write-a-shell-in-c/) 📝 83 | 84 | #### External Functions 85 | 86 | Reviewed the external functions allowed, dividing them among ourselves to research and explain their usage to the team. 87 | 88 | **Readline Functions:** 89 | 90 | | Function | Description | 91 | | ------------------- | ------------------------------------------------------------- | 92 | | `readline` | Reads a line from the standard input and returns it. | 93 | | `rl_clear_history` | Clears the readline history list. | 94 | | `rl_on_new_line` | Prepares readline for reading input on a new line. | 95 | | `rl_replace_line` | Replaces the content of the readline current line buffer. | 96 | | `rl_redisplay` | Updates the display to reflect changes to the input line. | 97 | | `add_history` | Adds the most recent input to the readline history list. | 98 | 99 | **Standard I/O Functions:** 100 | 101 | | Function | Description | 102 | | ---------- | ------------------------------------------------------- | 103 | | `printf` | Outputs formatted data to stdout. | 104 | 105 | **Memory Allocation Functions:** 106 | 107 | | Function | Description | 108 | | ---------- | ------------------------------------------------------- | 109 | | `malloc` | Allocates specified bytes of heap memory. | 110 | | `free` | Deallocates previously allocated memory. | 111 | 112 | **File I/O Functions:** 113 | 114 | | Function | Description | 115 | | ---------- | ------------------------------------------------------------- | 116 | | `write` | Writes data to a file descriptor. | 117 | | `access` | Checks calling process's permissions for a file or directory. | 118 | | `open` | Opens a file or device, returning a file descriptor. | 119 | | `read` | Reads data from a file descriptor into a buffer. | 120 | | `close` | Closes a previously opened file descriptor. | 121 | 122 | **Process Control Functions:** 123 | 124 | | Function | Description | 125 | | ------------- | ------------------------------------------------------------------ | 126 | | `fork` | Creates a new process by duplicating the calling process. | 127 | | `wait` | Suspends execution of the calling process until one of its children terminates. | 128 | | `waitpid` | Waits for a specific child process to change state. | 129 | | `wait3` | Waits for any child process to change state. | 130 | | `wait4` | Waits for a specific child process to change state. | 131 | | `signal` | Handles or ignores signals sent to the process. | 132 | | `sigaction` | Handles or ignores signals sent to the process. | 133 | | `sigemptyset`| Initializes and adds signals to a signal set. | 134 | | `sigaddset` | Initializes and adds signals to a signal set. | 135 | | `kill` | Sends a signal to a process or a group of processes. | 136 | | `exit` | Terminates the calling process. | 137 | 138 | **Directory Functions:** 139 | 140 | | Function | Description | 141 | | ---------- | ------------------------------------------------------- | 142 | | `getcwd` | Gets the current working directory. | 143 | | `chdir` | Changes the current working directory. | 144 | | `stat` | Returns information about a file or a file descriptor. | 145 | | `lstat` | Returns information about a file or a file descriptor. | 146 | | `fstat` | Returns information about a file or a file descriptor. | 147 | | `unlink` | Removes a link to a file. | 148 | | `execve` | Replaces the current process image with a new process image. | 149 | 150 | **File Descriptor Functions:** 151 | 152 | | Function | Description | 153 | | ---------- | ------------------------------------------------------- | 154 | | `dup` | Duplicates a file descriptor. | 155 | | `dup2` | Duplicates a file descriptor. | 156 | | `pipe` | Creates a pipe for inter-process communication. | 157 | 158 | **Directory Functions:** 159 | | Function | Description | 160 | | ---------- | ------------------------------------------------------- | 161 | | `opendir` | Manages directory streams. | 162 | | `readdir` | Manages directory streams. | 163 | | `closedir` | Manages directory streams. | 164 | 165 | **Error Handling Functions:** 166 | | Function | Description | 167 | | ---------- | ------------------------------------------------------- | 168 | | `strerror` | Returns a pointer to the textual representation of an error code. | 169 | | `perror` | Returns a pointer to the textual representation of an error code. | 170 | 171 | **Terminal Functions:** 172 | | Function | Description | 173 | | ------------- | ------------------------------------------------------------------ | 174 | | `isatty` | Tests whether a file descriptor refers to a terminal. | 175 | | `ttyname` | Returns the name of the terminal associated with a file descriptor.| 176 | | `ttyslot` | Returns the name of the terminal associated with a file descriptor.| 177 | | `ioctl` | Controls device-specific input/output operations. | 178 | | `getenv` | Returns the value of an environment variable. | 179 | | `tcsetattr` | Sets and gets terminal attributes. | 180 | | `tcgetattr` | Sets and gets terminal attributes. | 181 | | `tgetent` | Terminal handling functions from the termcap library. | 182 | | `tgetflag` | Terminal handling functions from the termcap library. | 183 | | `tgetnum` | Terminal handling functions from the termcap library. | 184 | | `tgetstr` | Terminal handling functions from the termcap library. | 185 | | `tgoto` | Terminal handling functions from the termcap library. | 186 | | `tput` | Terminal handling functions from the termcap library. | 187 | 188 | ### Step 3: Parsing and Input Management 189 | 190 | - [Parsing - Computerphile](https://youtu.be/r6vNthpQtSI?list=LL) 191 | - [Learn About Parsing - What is it and Why Do You Need It?](https://youtu.be/T0BO415l3N0?list=LL) 192 | 193 | #### Command Reading 194 | 195 | **Readline Library**: Implemented readline and integrated add_history ( [GNU Readline](https://en.wikipedia.org/wiki/GNU_Readline)) 196 | 197 | ```bash 198 | brew install readline 199 | ``` 200 | [readline(3) - Linux manual page](https://man7.org/linux/man-pages/man3/readline.3.html) 201 | 202 | Add the following to the Makefile: 203 | ```makefile 204 | READLINE_INCLUDE = $(shell brew --prefix readline)/include 205 | READLINE_LIB = $(shell brew --prefix readline)/lib 206 | INCLUDES = -I./includes -I./lib/libft -I$(READLINE_INCLUDE) 207 | ``` 208 | 209 | ```c 210 | #include 211 | #include 212 | #include 213 | 214 | int main(void) 215 | { 216 | char *input; 217 | 218 | while (1) 219 | { 220 | input = readline("minishell$ "); 221 | if (!input) 222 | break; 223 | if (*input) 224 | add_history(input); 225 | printf("Input: %s\n", input); 226 | free(input); 227 | } 228 | return 0; 229 | } 230 | ``` 231 | 232 | 233 | ### Steps for building the parser and AST (Abstract Syntax Tree) 234 | 235 | [What Is An Abstract Syntax Tree](https://youtu.be/wINY109MG10?list=LL) 236 | 237 | 238 | - **Syntax Error Checking**: This involves verifying whether the input string adheres to the shell's syntax rules. It checks for unclosed quotes, and misuse of redirection or pipe symbols. Syntax error checking ensures that the input can be correctly interpreted and executed. 239 | 240 | ![bash-quotes](https://github.com/user-attachments/assets/13f1ff3a-d537-477c-a37e-377a8c29ab5c) 241 | 242 | - **Tokenization**: This step breaks the input string into meaningful pieces, known as tokens. Tokens can be commands, arguments, redirection operators (`<`, `>`, `>>`, `<<`), pipe symbols (`|`), and environment variable identifiers. Tokenization simplifies the parsing process by converting the input string into a format that's easier to analyze. 243 | - **Parsing**: During parsing, tokens are analyzed to understand their syntactical relationship. This step involves constructing a representation of the input that reflects the user's intention. Depending on the complexity of the shell, this could mean building an abstract syntax tree (AST) or a simpler structure. 244 | - **AST Construction**: 245 | - **Commands**: Nodes in the AST represent commands along with their arguments. These nodes are fundamental to understanding what actions the shell needs to perform. 246 | - **Redirections**: Redirection nodes are created to represent input and output redirections. These nodes are attached to command nodes to modify how the commands read their input or write their output. 247 | - **Pipelines**: When a pipe is encountered, a pipeline node links command nodes together, indicating that the output of one command serves as the input to another. 248 | - **Environment Variable Expansion**: This can be handled as part of command parsing or immediately before command execution. It involves replacing environment variable identifiers with their corresponding values. 249 | 250 | - **Execution AST**: After the AST is built, it is traversed to execute the commands it represents. This involves: 251 | - Executing built-in commands directly within the shell. 252 | - Launching external commands by creating new processes. 253 | - Setting up redirections as specified by the redirection nodes. 254 | - Managing pipelines by connecting the stdout of one command to the stdin of the next. 255 | 256 | #### a. Designing a Syntax Error Checker 257 | 258 | the syntax error checker will be responsible for identifying and reporting syntax errors in the user input. 259 | 260 | 1. **Unclosed Quotes**: verify that all quotes are properly closed. 261 | 2. **Misplaced Operators**: Detect if pipes `|` are used incorrectly, such as being at the start or end of the input, or if multiple pipes are used consecutively. 262 | 3. **Logical Operators**: Detect logical operators such as `&&` and `||` and report them as not supported. 263 | 4. **Invalid Redirections**: Detect invalid redirections, such as multiple consecutive redirections or redirections at the start or end of the input. 264 | 265 | #### b. Syntax Error Checker Function 266 | 267 | syntax_checker.c: 268 | 269 | - `syntax_error_checker` Function: Iterates through the input string, checking for syntax errors and reporting them if found. 270 | - `has_unclosed_quotes` Function: Checks for unclosed quotes in the input string. 271 | - `has_invalid_redirections` Function: Detects invalid redirections, such as multiple consecutive redirections or redirections at the start or end of the input. 272 | - `has_misplaced_operators` Function: Detects misplaced pipes and redirections. 273 | - `has_logical_operators` Function: Detects logical operators such as `&&` and `||` and reports them as not supported. 274 | 275 | 276 | #### c. Tokenization 277 | 278 | The goal of the tokenization process is to break down the input string into a series of tokens that the parser can easily understand. These tokens represent commands, arguments, pipes, redirections, and other elements of the shell syntax. 279 | 280 | - **Quotations**: Distinguishing between single (`'`) and double (`"`) quotes. 281 | - **Redirections**: Recognizing input (`<`), output (`>`), append (`>>`), and here-documen(`<<`) redirections. 282 | - **Pipes** (`|`): Splitting commands to be executed in a pipeline. 283 | - **Environment variables**: Expanding variables starting with `$`. 284 | - **Command separation**: Identifying commands and their arguments. 285 | 286 | #### d. Token Structure 287 | 288 | ```c 289 | // Token type enumeration 290 | typedef enum e_token_type 291 | { 292 | TOKEN_WORD, // For commands and arguments 293 | TOKEN_PIPE, // For '|' 294 | TOKEN_REDIR_IN, // For '<' 295 | TOKEN_REDIR_OUT, // For '>' 296 | TOKEN_REDIR_APPEND, // For '>>' 297 | TOKEN_REDIR_HEREDOC, // For '<<' 298 | TOKEN_ENV_VAR, // For environment variables 299 | } t_token_type; 300 | 301 | // Token structure 302 | typedef struct s_token 303 | { 304 | t_token_type type; 305 | char *value; 306 | struct s_token *next; 307 | } t_token; 308 | ``` 309 | 310 | #### e. Tokenization Strategy 311 | 312 | 1. **Whitespace Handling**: Skip whitespace outside quotes to separate commands and arguments. 313 | 2. **Quoting**: Correctly handle single (`'`) and double quotes (`"`), preserving the text exactly as is within single quotes and allowing for variable expansion and escaped characters within double quotes. 314 | 3. **Redirections and Pipes**: Detect `>`, `>>`, `<`, `<<`, and `|`, treating them as separate tokens while managing any adjacent whitespace. 315 | 316 | #### f. Tokenization Function 317 | 318 | The tokenization function will iterate through the input string, identifying and categorizing segments according to the shell syntax. 319 | 320 | tokenization.c: 321 | 322 | - `tokenize_input` Function: Iterates through the input, creating tokens for words separated by spaces. 323 | - `handle_special_chars` Function: Handles the special characters in the input string. 324 | - `handle_word` Function: Handles the words in the input string. 325 | - `print_tokens` Function: Prints the tokens to verify the tokenization process. 326 | 327 | Example: 328 | 329 | ```bahs 330 | > ls -l | wc -l > output.txt | ls > output2.txt 331 | Token: ls | Type: WORD 332 | -------------------------------------------------- 333 | Token: -l | Type: WORD 334 | -------------------------------------------------- 335 | Token: | | Type: PIPE 336 | -------------------------------------------------- 337 | Token: wc | Type: WORD 338 | -------------------------------------------------- 339 | Token: -l | Type: WORD 340 | -------------------------------------------------- 341 | Token: > | Type: REDIRECT_OUT 342 | -------------------------------------------------- 343 | Token: output.txt | Type: WORD 344 | -------------------------------------------------- 345 | Token: | | Type: PIPE 346 | -------------------------------------------------- 347 | Token: ls | Type: WORD 348 | -------------------------------------------------- 349 | Token: > | Type: REDIRECT_OUT 350 | -------------------------------------------------- 351 | Token: output2.txt | Type: WORD 352 | -------------------------------------------------- 353 | ``` 354 | 355 | #### g. Parsing 356 | 357 | The parsing process involves analyzing the tokens to understand their syntactical relationship. This step constructs a representation of the input that reflects the user's intention. 358 | 359 | - **Command Parsing**: Parsing commands and their arguments, creating command nodes in the AST. 360 | - **Pipeline Parsing**: Parsing pipeline tokens, creating pipeline nodes in the AST. 361 | - **Redirection Parsing**: Parsing redirection tokens, creating redirection nodes in the AST. 362 | - **File Node Creation**: Creating a file node for redirections in the AST. 363 | 364 | #### h .AST Node Structure 365 | 366 | The AST node structure will represent the input string in a way that reflects the user's intention. The AST will be composed of nodes that represent commands, arguments, redirections, and pipelines. 367 | 368 | ```c 369 | typedef struct s_ast_node 370 | { 371 | t_node type type; 372 | char *args; 373 | struct s_ast_node *left; 374 | struct s_ast_node *right; 375 | } t_ast_node; 376 | ``` 377 | 378 | #### i. Parsing Function 379 | 380 | The parsing function will iterate through the tokens, building an abstract syntax tree (AST) that represents the input string. 381 | 382 | parse.c: 383 | 384 | - `parse_tokens` Function: Iterates through the tokens, building an abstract syntax tree (AST) that represents the input string. 385 | - `parse_command` Function: Parses a command and its arguments, creating a command node in the AST. 386 | - `parse_pipeline` Function: Parses pipeline tokens, creating pipeline nodes in the AST. 387 | - `parse_redirection` Function: Parses redirection tokens, creating redirection nodes in the AST. 388 | - `create_file_node` Function: Creates a file node for redirections in the AST. 389 | 390 | #### j. AST Visualization 391 | 392 | generate_ast_diagram/generate_ast_diagram.c: 393 | 394 | - `generate_ast_diagram` Function: Generates a visual representation of the AST, showing the structure of the input string. 395 | 396 | Example: 397 | ```bash 398 | ls -l | wc -l > output.txt | ls > output2.txt 399 | ``` 400 | 401 | ![graphviz](https://github.com/zelhajou/42-minishell/assets/39954629/e8cbd784-3ee1-4642-803c-3b903cbb7afe) 402 | 403 | [GraphvizOnline](https://dreampuf.github.io/GraphvizOnline/#digraph%20AST%20%7B%0A%220x7ff812f05540%22%20%5Blabel%3D%22%7C%22%5D%3B%0A%220x7ff812f05540%22%20-%3E%20%220x7ff812f05560%22%20%5Blabel%3D%22L%22%5D%3B%0A%220x7ff812f05560%22%20%5Blabel%3D%22CMD%3A%20ls%20-l%22%5D%3B%0A%220x7ff812f05540%22%20-%3E%20%220x7ff812f05360%22%20%5Blabel%3D%22R%22%5D%3B%0A%220x7ff812f05360%22%20%5Blabel%3D%22%7C%22%5D%3B%0A%220x7ff812f05360%22%20-%3E%20%220x7ff812f05300%22%20%5Blabel%3D%22L%22%5D%3B%0A%220x7ff812f05300%22%20%5Blabel%3D%22REDIR%3A%20%22%5D%3B%0A%220x7ff812f05300%22%20-%3E%20%220x7ff812f05320%22%20%5Blabel%3D%22L%22%5D%3B%0A%220x7ff812f05320%22%20%5Blabel%3D%22CMD%3A%20wc%20-l%22%5D%3B%0A%220x7ff812f05300%22%20-%3E%20%220x7ff812f053f0%22%20%5Blabel%3D%22R%22%5D%3B%0A%220x7ff812f053f0%22%20%5Blabel%3D%22CMD%3A%20output.txt%22%5D%3B%0A%220x7ff812f05360%22%20-%3E%20%220x7ff812f05420%22%20%5Blabel%3D%22R%22%5D%3B%0A%220x7ff812f05420%22%20%5Blabel%3D%22REDIR%3A%20%22%5D%3B%0A%220x7ff812f05420%22%20-%3E%20%220x7ff812f05450%22%20%5Blabel%3D%22L%22%5D%3B%0A%220x7ff812f05450%22%20%5Blabel%3D%22CMD%3A%20ls%22%5D%3B%0A%220x7ff812f05420%22%20-%3E%20%220x7ff812f054b0%22%20%5Blabel%3D%22R%22%5D%3B%0A%220x7ff812f054b0%22%20%5Blabel%3D%22CMD%3A%20output2.txt%22%5D%3B%0A%7D%0A) 404 | 405 | ### Step 4: Command Execution 406 | 407 | - **Built-in Commands**: Implementing internal versions of several built-in commands (`echo`, `cd`, `pwd`, `export`, `unset`, `env`, `exit`) that behave consistently with their bash counterparts. 408 | 409 | ![builtins](https://github.com/user-attachments/assets/ce5fba5b-96bc-44d8-88be-b5a39b0b362e) 410 | 411 | - **External Commands**: Implementing logic to search for and execute the right executable based on the PATH environment variable or a specified path. 412 | 413 | ![path](https://github.com/user-attachments/assets/88709685-dfae-49c5-85e6-e4d45f0a1dd9) 414 | 415 | - **Process Creation**: Using system calls like `fork`, `execve`, `wait`, and `pipe` to manage process creation and execution. 416 | 417 | ![processes (1)](https://github.com/user-attachments/assets/5c7a2793-78ff-4dd5-bd01-a208457fd9cf) 418 | 419 | - **Redirection and Pipes**: Implementing input and output redirection (`<`, `>`, `>>`, `<<`) and pipes (`|`) to allow for command chaining and data redirection. 420 | 421 | ![redirects](https://github.com/user-attachments/assets/cc07277b-2fe0-425a-ba39-0013f9871d1c) 422 | ![pipes](https://github.com/user-attachments/assets/3cbc7f85-53e7-4312-bf3d-1b9053533ece) 423 | ![bash-pipes](https://github.com/user-attachments/assets/90379cd6-43f8-44f6-b089-958bed58a3a9) 424 | 425 | ### Step 5: Built-in Commands Implementation 426 | 427 | ![builtins](https://github.com/user-attachments/assets/ce5fba5b-96bc-44d8-88be-b5a39b0b362e) 428 | 429 | - **echo**: Outputs the arguments passed to it. 430 | - **cd**: Changes the current working directory. 431 | - **pwd**: Prints the current working directory. 432 | - **export**: Sets environment variables. 433 | - **unset**: Unsets environment variables 434 | - **env**: Prints the environment variables. 435 | 436 | ![environment-variables](https://github.com/user-attachments/assets/87e4570b-e029-4f0e-a38c-f31837e0612e) 437 | 438 | - **exit**: Exits the shell. 439 | 440 | ### Step 6: Signal Handling 441 | 442 | ![signals](https://github.com/user-attachments/assets/308b83ea-ad8f-4bcd-ba32-0cf79bf1b71f) 443 | 444 | - **SIGINT**: Handling the `ctrl-C` signal to interrupt the shell's execution. 445 | - **SIGQUIT**: Handling the `ctrl-\` signal to quit the shell. 446 | - **EOF**: Handling the `ctrl-D` signal to exit the shell. 447 | 448 | ### Step 7: Environment Variable Expansion 449 | 450 | - **Environment Variable Expansion**: Managing environment variables and supporting their expansion within commands, including the special case of `$?` to represent the exit status of the most recently executed command. 451 | 452 | ![parameter-expansion](https://github.com/user-attachments/assets/c1824c1c-7d2a-4244-ae4c-e95d063c4a45) 453 | 454 | ### Step 8: Testing and Debugging 455 | 456 | - [reda ghouzraf](https://github.com/rghouzra) : The most skilled human tester in the world 457 | - [Minishell Tests](https://docs.google.com/spreadsheets/d/1BLU6C9S7aoCl01x74GiW7s4xpEWWJ1cPrMTcLwISruk/edit#gid=1627853444) 458 | - 459 | - 460 | 461 | 462 | ## Project Structure 463 | 464 | ```bash 465 | ├── includes 466 | │ └── minishell.h 467 | ├── lib 468 | │ └── libft 469 | ├── Makefile 470 | └── src 471 | ├── 01_input_validation 472 | ├── 02_tokenization 473 | ├── 03_parsing 474 | ├── 04_execution 475 | ├── 05_builtin 476 | ├── 06_signals 477 | ├── 07_env_var_expansion 478 | ├── main.c 479 | └── utils 480 | ``` 481 | 482 | ## Team Members 483 | 484 | - [Bilal Edd](https://github.com/edbilal) 485 | - [Zakaria Elhajoui](https://github.com/zelhajou) 486 | 487 | ## Resources 488 | 489 | - 490 | - 491 | - 492 | - 493 | - 494 | - 495 | 496 | ## Acknowledgements 497 | 498 | Thanks to [reda ghouzraf](https://github.com/rghouzra), [MTRX](https://github.com/whoismtrx), [Nasreddine hanafi](https://github.com/Nx21), [Khalid zerri](https://github.com/zerrikhalid) for their help and support during the project. 499 | -------------------------------------------------------------------------------- /doc/Chapter5-WritingYourOwnShell.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zelhajou/ft_unix_minishell/9bc7572658ae5d3938fce082dd15c0d844ce008a/doc/Chapter5-WritingYourOwnShell.pdf -------------------------------------------------------------------------------- /doc/EQ04If9XYAAaGJK.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zelhajou/ft_unix_minishell/9bc7572658ae5d3938fce082dd15c0d844ce008a/doc/EQ04If9XYAAaGJK.jpeg -------------------------------------------------------------------------------- /doc/Subject/en.subject.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zelhajou/ft_unix_minishell/9bc7572658ae5d3938fce082dd15c0d844ce008a/doc/Subject/en.subject.pdf -------------------------------------------------------------------------------- /doc/book-rev7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zelhajou/ft_unix_minishell/9bc7572658ae5d3938fce082dd15c0d844ce008a/doc/book-rev7.pdf -------------------------------------------------------------------------------- /doc/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef struct s_node { 7 | char *value; 8 | struct s_node *left; 9 | struct s_node *right; 10 | } t_node; 11 | 12 | t_node *create_node(char *value) { 13 | t_node *node = (t_node *)malloc(sizeof(t_node)); 14 | node->value = value; 15 | node->left = NULL; 16 | node->right = NULL; 17 | return node; 18 | } 19 | 20 | 21 | t_node *parseTree(char *input) { 22 | t_node *root = NULL; 23 | t_node *current = NULL; 24 | t_node *parent = NULL; 25 | int i = 0; 26 | while (input[i] != '\0') { 27 | 28 | } 29 | return root; 30 | } 31 | 32 | void print_tree(t_node *root) { 33 | if (root == NULL) { 34 | return; 35 | } 36 | printf("%s\n", root->value); 37 | print_tree(root->left); 38 | print_tree(root->right); 39 | } 40 | t_node *multip(char *s); 41 | t_node *plus(char *s) 42 | { 43 | for (size_t i = 0; s && s[i]; i++) 44 | { 45 | if (s[i] == '+' || s[i] == '-') 46 | { 47 | t_node *node = create_node(s[i] == '+' ? "+" : "-"); 48 | s[i] = '\0'; 49 | node->left = multip(s); 50 | node->right = plus(s + i + 1); 51 | return node; 52 | } 53 | } 54 | return multip(s); 55 | } 56 | t_node *multip(char *s) 57 | { 58 | for (size_t i = 0; s && s[i]; i++) 59 | { 60 | if (s[i] == '*' || s[i] == '/') 61 | { 62 | t_node *node = create_node(s[i] == '*' ? "*" : "/"); 63 | s[i] = '\0'; 64 | node->left = multip(s); 65 | node->right = create_node(s + i + 1); 66 | return node; 67 | } 68 | } 69 | return create_node((s)); 70 | } 71 | 72 | int main() { 73 | char *input = readline("Calculate: "); 74 | 75 | t_node *root = plus(input); 76 | print_tree(root); 77 | 78 | 79 | return 0; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /doc/witeboard_cfc66f20-d1b8-11ee-8005-578a88b9ab70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zelhajou/ft_unix_minishell/9bc7572658ae5d3938fce082dd15c0d844ce008a/doc/witeboard_cfc66f20-d1b8-11ee-8005-578a88b9ab70.png -------------------------------------------------------------------------------- /generate_ast_diagram/generate_ast_diagram.c: -------------------------------------------------------------------------------- 1 | #include "minishell.h" 2 | 3 | void print_escaped(FILE *stream, const char *str) 4 | { 5 | if (!str) return; 6 | while (*str) 7 | { 8 | switch (*str) 9 | { 10 | case '\n': fprintf(stream, "\\n"); break; 11 | case '\"': fprintf(stream, "\\\""); break; 12 | case '\\': fprintf(stream, "\\\\"); break; 13 | default: fputc(*str, stream); 14 | } 15 | str++; 16 | } 17 | } 18 | 19 | void print_ast_dot(t_ast_node *node, FILE *stream) 20 | { 21 | if (node == NULL) return; 22 | 23 | fprintf(stream, "\"%p\" [label=\"", (void*)node); 24 | // Print node type 25 | switch (node->type) 26 | { 27 | // Adjust these labels based on your specific types and what they represent 28 | case TOKEN_WORD: fprintf(stream, "CMD: "); break; 29 | case TOKEN_REDIR_IN: 30 | case TOKEN_REDIR_OUT: 31 | case TOKEN_REDIR_APPEND: 32 | case TOKEN_REDIR_HEREDOC: fprintf(stream, "REDIR: "); break; 33 | case TOKEN_PIPE: fprintf(stream, "|"); break; 34 | default: fprintf(stream, "UNKNOWN"); break; 35 | } 36 | // Print all arguments for the node 37 | if (node->args) 38 | { 39 | for (int i = 0; node->args[i] != NULL; i++) 40 | { 41 | if (i > 0) fprintf(stream, " "); // Add space between arguments 42 | print_escaped(stream, node->args[i]); 43 | } 44 | } 45 | fprintf(stream, "\"];\n"); 46 | if (node->left != NULL) 47 | { 48 | fprintf(stream, "\"%p\" -> \"%p\" [label=\"L\"];\n", (void*)node, (void*)node->left); 49 | print_ast_dot(node->left, stream); 50 | } 51 | if (node->right != NULL) 52 | { 53 | fprintf(stream, "\"%p\" -> \"%p\" [label=\"R\"];\n", (void*)node, (void*)node->right); 54 | print_ast_dot(node->right, stream); 55 | } 56 | } 57 | 58 | void generate_ast_diagram(t_ast_node *root) 59 | { 60 | FILE *stream = fopen("ast.dot", "w"); 61 | if (stream == NULL) 62 | { 63 | perror("fopen"); 64 | return; 65 | } 66 | 67 | fprintf(stream, "digraph AST {\n"); 68 | print_ast_dot(root, stream); 69 | fprintf(stream, "}\n"); 70 | fclose(stream); 71 | } -------------------------------------------------------------------------------- /minishell/Makefile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Makefile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: zelhajou +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2024/02/10 20:09:25 by zelhajou #+# #+# # 9 | # Updated: 2024/03/10 15:46:14 by zelhajou ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | NAME = minishell 14 | CC = cc 15 | CFLAGS = -Wall -Wextra -Werror 16 | READLINE_INCLUDE = $(shell brew --prefix readline)/include 17 | READLINE_LIB = $(shell brew --prefix readline)/lib 18 | INCLUDES = -I./includes -I./lib/libft -I./lib/get_next_line -I$(READLINE_INCLUDE) 19 | SRCDIR = ./src 20 | OBJDIR = ./obj 21 | LIBFTDIR = ./lib/libft 22 | LIBGNTLDIR = ./lib/get_next_line 23 | READLINEDIR = ./lib/readline 24 | 25 | SRCS = $(SRCDIR)/main.c \ 26 | $(SRCDIR)/01_input_validation/syntax_checker.c \ 27 | $(SRCDIR)/01_input_validation/syntax_checker_utils.c \ 28 | $(SRCDIR)/02_tokenization/tokenizer.c \ 29 | $(SRCDIR)/02_tokenization/tokenizer_utils.c \ 30 | $(SRCDIR)/02_tokenization/print_tokens.c \ 31 | $(SRCDIR)/03_parsing/parser.c \ 32 | $(SRCDIR)/03_parsing/parser_utils.c \ 33 | $(SRCDIR)/04_execution/initialization/command_execution_init.c \ 34 | $(SRCDIR)/04_execution/initialization/environment_init.c \ 35 | $(SRCDIR)/04_execution/builtin_command_execution.c \ 36 | $(SRCDIR)/04_execution/builtin_command_execution2.c \ 37 | $(SRCDIR)/04_execution/command_execution_adv.c \ 38 | $(SRCDIR)/04_execution/executor.c \ 39 | $(SRCDIR)/04_execution/path_utilities.c \ 40 | $(SRCDIR)/04_execution/path_utilities2.c \ 41 | $(SRCDIR)/04_execution/process_pipeline_management.c \ 42 | $(SRCDIR)/04_execution/command_execution_control.c \ 43 | $(SRCDIR)/04_execution/command_input_preprocessing.c \ 44 | $(SRCDIR)/04_execution/heredoc_handling.c \ 45 | $(SRCDIR)/05_builtin/builtin_commands.c \ 46 | $(SRCDIR)/05_builtin/builtin_commands_utils.c \ 47 | $(SRCDIR)/05_builtin/builtin_commands_utils2.c \ 48 | $(SRCDIR)/05_builtin/builtin_commands_utils3.c \ 49 | $(SRCDIR)/06_signals/signal_handlers.c \ 50 | $(SRCDIR)/07_env_var_expansion/env_handling.c \ 51 | $(SRCDIR)/07_env_var_expansion/env_managment.c \ 52 | $(SRCDIR)/07_env_var_expansion/env_managment2.c \ 53 | $(SRCDIR)/07_env_var_expansion/variable_expansion.c \ 54 | $(SRCDIR)/07_env_var_expansion/variable_expansion_utils.c \ 55 | $(SRCDIR)/utils/string_utilities/string_utils.c \ 56 | $(SRCDIR)/utils/string_utilities/string_utils2.c \ 57 | $(SRCDIR)/utils/shell_utilities.c \ 58 | 59 | OBJS = $(SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o) 60 | LDFLAGS = -L$(LIBFTDIR) -lft -L$(READLINE_LIB) -lreadline 61 | LIBFT = $(LIBFTDIR)/libft.a 62 | 63 | all: $(NAME) 64 | 65 | $(NAME): $(LIBFT) $(OBJS) 66 | $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(NAME) 67 | 68 | $(OBJDIR)/%.o: $(SRCDIR)/%.c ./includes/minishell.h 69 | @mkdir -p $(@D) 70 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 71 | 72 | $(LIBFT): 73 | $(MAKE) -C $(LIBFTDIR) 74 | 75 | clean: 76 | rm -rf $(OBJDIR) 77 | $(MAKE) -C $(LIBFTDIR) clean 78 | 79 | fclean: clean 80 | rm -f $(NAME) 81 | $(MAKE) -C $(LIBFTDIR) fclean 82 | 83 | re: fclean all 84 | 85 | .PHONY: all clean fclean re 86 | -------------------------------------------------------------------------------- /minishell/includes/minishell.h: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* minishell.h :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/18 16:43:38 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/10 14:14:21 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef MINISHELL_H 14 | # define MINISHELL_H 15 | 16 | # define READ_FILE 10 17 | # define READ_FROM_APPEND 15 18 | # define WRITE_FILE 20 19 | # define WRITE_FILE_APPEND 30 20 | # define EXECUTE_FILE 40 21 | # define FILE_READY 50 22 | 23 | # include 24 | # include 25 | # include 26 | # include 27 | # include 28 | # include 29 | # include 30 | # include 31 | # include 32 | # include 33 | # include 34 | # include 35 | # include "libft.h" 36 | 37 | extern int g_var_thing; 38 | 39 | typedef enum e_token_type 40 | { 41 | TOKEN_WORD, 42 | TOKEN_PIPE, 43 | TOKEN_REDIR_IN, 44 | TOKEN_REDIR_OUT, 45 | TOKEN_REDIR_APPEND, 46 | TOKEN_REDIR_HEREDOC, 47 | TOKEN_ENV_VAR, 48 | } t_token_type; 49 | 50 | typedef struct s_token 51 | { 52 | t_token_type type; 53 | char *value; 54 | struct s_token *next; 55 | } t_token; 56 | 57 | typedef struct s_ast_node 58 | { 59 | t_token_type type; 60 | int file_type; 61 | char **args; 62 | struct s_ast_node *left; 63 | struct s_ast_node *right; 64 | } t_ast_node; 65 | 66 | typedef struct s_env 67 | { 68 | char **original_env; 69 | char ***parsed_env; 70 | } t_env; 71 | 72 | void __exit(char **_cmd_); 73 | int export_print_or_export(char **_cmd_); 74 | /* ------------------ Main Shell Functionality ------------------ */ 75 | 76 | void main_shell_execution_loop(t_env *env); 77 | void setup_signal_handlers(void); 78 | void handle_ctrl_c(int sig_num); 79 | void child_ctrl_c(int sig_num); 80 | 81 | /* ------------------ Input Processing ------------------ */ 82 | 83 | t_token *process_and_tokenize_input(char *input); 84 | 85 | /* ------------------ Syntax Analysis ------------------ */ 86 | 87 | int syntax_error_checker(const char *input); 88 | int has_unclosed_quotes(const char *input); 89 | int has_invalid_redirections(const char *input); 90 | int has_misplaced_operators(const char *input); 91 | int has_logical_operators(const char *input); 92 | void update_quote_counts(char c, int *s_q_count, int *d_q_count); 93 | const char *skip_spaces(const char *input); 94 | int is_invalid_operator(const char **input); 95 | void update_quote_status(char c, int *in_quote, char *quote_char); 96 | void add_word_token_if_valid(char **start, char **input, 97 | t_token **tokens); 98 | 99 | /* ------------------ Token Management ------------------ */ 100 | 101 | t_token *new_token(t_token_type type, char *value); 102 | void add_token_to_list(t_token **tokens, t_token *new_token); 103 | void free_tokens(t_token *tokens); 104 | void handle_quotes(char **input, t_token **tokens); 105 | void handle_special_chars(char **input, t_token **tokens); 106 | void handle_word(char **input, t_token **tokens); 107 | t_token *tokenize_input(char *input); 108 | 109 | /* ------------------ AST Construction and Management ------------------ */ 110 | 111 | t_ast_node *new_ast_node(t_token_type type); 112 | void free_ast(t_ast_node *node); 113 | t_ast_node *parse_tokens(t_token **tokens); 114 | t_ast_node *parse_command(t_token **tokens); 115 | int count_command_arguments(t_token *current); 116 | void fill_command_arguments(t_ast_node *command_node, 117 | t_token **tokens, int arg_count); 118 | t_ast_node *parse_pipeline(t_token **tokens); 119 | t_ast_node *parse_redirection(t_token **tokens); 120 | t_ast_node *create_file_node(t_token *token); 121 | t_ast_node *create_and_link_redirection(t_token **tokens, t_token *tmp); 122 | 123 | /* ------------------ Built-in Command Execution ------------------ */ 124 | 125 | int cd_cmd(char **cmd, t_env *env, int *out_fd); 126 | int echo_cmd(char **cmd, int *out_fd); 127 | int env_or_pwd_cmd(char *cmd, t_env *env, int condition, int *out_fd); 128 | char **export_cmd(char **cmd, t_env *env, int *out_fd, int **status); 129 | char **unset_or_export_cmd(char **cmd, t_env *env, 130 | int *out_fd, int *status); 131 | 132 | /* ------------------ Built-in Command Utilities ------------------ */ 133 | 134 | void set_new_pwd_in_env(char *new_path, t_env *env, int unused); 135 | int change_current_directory(char *path, t_env *env); 136 | char *get_current_working_directory(int size, int tries, int fd); 137 | int export_statment_check(char *_cmd_); 138 | 139 | /* ------------------ Input Validation and Environment Management -------- */ 140 | 141 | int check_line(char **line); 142 | int find_env_var_index(t_env *env, char *name); 143 | void free_environment_variables(char ***array); 144 | void replace_env_var(char *var, t_env *env); 145 | void append_env_var(char *var, t_env *env); 146 | int is_string_numeric(char *s_1); 147 | 148 | /* ------------------ Printing and Utility Functions ------------------ */ 149 | 150 | void print_env_var_to_fd(char *key, char *value, int fd); 151 | void print_export_vars(char ***arr, int a, int fd); 152 | void print_export_declaration_to_fd(t_env *env, int *_out_fd); 153 | 154 | /* ------------------ Command Execution Management ------------------ */ 155 | 156 | void adjust_ast_nodes_for_execution(t_ast_node *head); 157 | void command_execution_manager(t_ast_node *head, 158 | t_env *env, int *status); 159 | int execute_ast_node(t_ast_node *head, int *piped, t_env *env); 160 | int prepare_and_execute_command(char **cmd, int *fd, 161 | int *piped, t_env *env); 162 | int handle_command_redirection(t_ast_node *head, int *piped, 163 | t_env *env, int *fd); 164 | int handle_piped_command_execution(t_ast_node *head, 165 | int *piped, t_env *env, int *fd); 166 | int exec_here_doc(char *limiter, int *piped, t_env *env); 167 | void initialize_or_reset_pipe_state(int *piped, int flag); 168 | int open_file_for_redirection( 169 | t_ast_node *head, int *piped, t_env *env, int status); 170 | int check_if_command_is_builtin(char *cmd); 171 | int manage_builtin_execution(char **cmd, int *fd, 172 | t_env *env, int *piped); 173 | int manage_single_builtin_execution(char **cmd, int *fd, 174 | t_env *env, int *piped); 175 | int execute_builtin_command_in_child(char **cmd, 176 | t_env *env, int *out_fd, int *_piped); 177 | 178 | /* ----------- Path and Environment Variable Handling --------- */ 179 | 180 | void increment_path_index(char *env_var, int *index_start, 181 | int *index_end); 182 | void add_env_entry(t_env *env, char *cmd, 183 | int bool_condition, int condition); 184 | void remove_env_entry(t_env *env, int index); 185 | void update_env_status(t_env *env, int status, char *start); 186 | int is_path_accessible(char *path, int mode); 187 | int env_just_print(t_env *env, int con, int *_out_fd); 188 | 189 | /* ------------------ String Manipulation and Checking ------------------ */ 190 | 191 | void s_strcopy(char *dest, char *src, int start, int end); 192 | char *strcopy(char *src); 193 | char *str_without_char(char *str, char delimiter); 194 | char *remove_quotes_from_str(char *str, int a, int b, int c); 195 | int str_cmp(char *str1, char *str2, char *str3); 196 | int is_space(char *line); 197 | int sizeof_str(char *str, char delimiter); 198 | int count_strings_in_array(char **arr); 199 | 200 | /* ------------------ Process and Pipeline Management ------------------ */ 201 | 202 | int wait_for_children(int status, int *piped); 203 | void count_redirections_and_pipes(t_ast_node *head, int *piped); 204 | void close_pipe_ends(int fd_1, int fd_2); 205 | void child_fds_managment(int *_piped, int *_fd, int *fd_); 206 | void parent_fds_managment(int *_piped, int *_fd, int *fd_); 207 | 208 | /* ------------------ Variable Expansion and Replacement ------------------ */ 209 | 210 | void expand_variables_in_ast(t_ast_node *head, t_env *env); 211 | char *recursively_expand_variables( 212 | char *var, t_env *env, int __con, int *f_arr); 213 | char *replace_variable_with_value(char *old_var, char *new_value, 214 | int start, int end); 215 | int simplified_refactor_thing(char **array, 216 | int index, char *str, int in); 217 | int is_flawed_str(char *str, int a, int b, int res); 218 | int detected_flaws(char **array); 219 | 220 | /* ------------------ Advanced String and Array Operations ------------------ */ 221 | 222 | int string_weight_compare(char *s_1, char *s_2); 223 | int check_array_arrangment(char ***array, int _si); 224 | char **merge_command_args(char **first_args, char **additional_args); 225 | char ***duplicate_env_structure(t_env *env, int a, int a_2, int d); 226 | int count_substrings(char *str, char delimiter); 227 | int find_substr_index(char **haystack, char *needle, int needle_length); 228 | char *find_next_substring(char *str, char delimiter, int *index); 229 | int string_to_int(char *str); 230 | int is_valid_variable_start(char *str, int index, int check_dollar); 231 | void free_string_array(char **arr); 232 | char *fetch_file_path(char *file, char **envp, char *env_var, int mode); 233 | char *create_subpath_from_var(char *env_var, char *file, 234 | int *index_start); 235 | int is_valid_echo_param(char *s); 236 | 237 | /* ------------------ Miscellaneous Utilities ------------------ */ 238 | 239 | int initialize_shell_with_environment(t_env *env, char **original_env); 240 | void cleanup_and_exit_shell(t_env *env, int status); 241 | int get_shell_exit_status(int error_code); 242 | int count_digits_in_int(int num); 243 | char **prepare_cmd_arguments(char *cmd, char **envp, int condition); 244 | int verify_command_file_permissions(t_ast_node *head, char **env); 245 | 246 | void generate_ast_diagram(t_ast_node *root); 247 | void display_tokens(t_token *tokens); 248 | 249 | #endif 250 | -------------------------------------------------------------------------------- /minishell/lib/libft/Makefile: -------------------------------------------------------------------------------- 1 | CC = cc 2 | CFLAGS = -Wall -Wextra -Werror 3 | NAME = libft.a 4 | HEADER = libft.h 5 | 6 | SRC = ft_isalpha.c ft_isdigit.c ft_isalnum.c ft_isascii.c ft_isprint.c ft_toupper.c ft_tolower.c ft_isspace.c \ 7 | ft_strlen.c ft_strnlen.c ft_strchr.c ft_strrchr.c ft_strnstr.c ft_strncmp.c ft_strlcpy.c ft_strlcat.c \ 8 | ft_bzero.c ft_memset.c ft_memcpy.c ft_memchr.c ft_memcmp.c ft_memmove.c \ 9 | ft_atoi.c ft_calloc.c ft_strdup.c ft_strndup.c \ 10 | ft_substr.c ft_strjoin.c ft_strtrim.c ft_split.c ft_putchar_fd.c ft_putstr_fd.c ft_putendl_fd.c ft_putnbr_fd.c \ 11 | ft_strmapi.c ft_striteri.c ft_itoa.c \ 12 | ft_lstnew.c ft_lstadd_front.c ft_lstsize.c ft_lstlast.c ft_lstadd_back.c ft_lstdelone.c ft_lstclear.c ft_lstiter.c \ 13 | 14 | OBJ = $(SRC:.c=.o) 15 | 16 | all: $(NAME) 17 | 18 | $(NAME): $(OBJ) 19 | ar -rcs $(NAME) $(OBJ) 20 | @echo "Libft Done !" 21 | 22 | %.o: %.c $(HEADER) 23 | $(CC) -c $(CFLAGS) $< 24 | 25 | clean: 26 | rm -rf $(OBJ) $(BOBJ) 27 | 28 | fclean: clean 29 | rm -rf $(NAME) $(BOBJ) 30 | 31 | re: fclean all 32 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_atoi.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_atoi.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/26 18:20:39 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/21 23:13:14 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_atoi() convert a string to an integer 15 | */ 16 | 17 | #include "libft.h" 18 | 19 | static int skip_space(int *i, const char *str) 20 | { 21 | int sign; 22 | 23 | sign = 1; 24 | while ((str[*i] >= 9 && str[*i] <= 13) || str[*i] == 32) 25 | (*i)++; 26 | if (str[*i] == '-' || str[*i] == '+') 27 | { 28 | if (str[*i] == '-') 29 | sign *= -1; 30 | (*i)++; 31 | } 32 | return (sign); 33 | } 34 | 35 | int ft_atoi(const char *str) 36 | { 37 | int sign; 38 | int i; 39 | long long res; 40 | long long prev; 41 | long long tmp; 42 | 43 | i = 0; 44 | res = 0; 45 | sign = skip_space(&i, str); 46 | while (str[i] >= '0' && str[i] <= '9') 47 | { 48 | prev = res; 49 | res = res * 10 + str[i] - '0'; 50 | tmp = res / 10; 51 | if (tmp != prev) 52 | { 53 | if (sign == 1) 54 | return (-1); 55 | else 56 | return (0); 57 | } 58 | i++; 59 | } 60 | return (sign * res); 61 | } 62 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_bzero.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_bzero.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/21 04:42:09 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:15 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_bzero() erases the data in the n bytes of the memory starting at 15 | the location pointed to by s, by writing zeros (bytes containing '\0') 16 | to that area. 17 | */ 18 | 19 | #include "libft.h" 20 | 21 | void ft_bzero(void *s, size_t n) 22 | { 23 | size_t i; 24 | unsigned char *str; 25 | 26 | i = 0; 27 | str = (unsigned char *)s; 28 | while (i < n) 29 | { 30 | str[i] = '\0'; 31 | i++; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_calloc.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_calloc.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/27 13:12:49 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:17 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_calloc() — Allocates the space for elements of an array. 15 | Initializes the elements to zero and returns a pointer to the memory. 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | void *ft_calloc(size_t nmemb, size_t size) 21 | { 22 | void *ptr; 23 | 24 | ptr = malloc(nmemb * size); 25 | if (ptr == NULL) 26 | return (NULL); 27 | ft_bzero(ptr, (nmemb * size)); 28 | return (ptr); 29 | } 30 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_isalnum.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_isalnum.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 10:15:57 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:19 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_isalnum() checks for an alphanumeric character; 15 | it is equivalent to (ft_isalpha(c) || ft_isdigit(c)). 16 | */ 17 | 18 | int ft_isalnum(int c) 19 | { 20 | if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') 21 | || (c >= '0' && c <= '9')) 22 | return (1); 23 | return (0); 24 | } 25 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_isalpha.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_isalpha.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 09:00:05 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:22 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_isalpha() checks for an alphabetic character 15 | */ 16 | 17 | int ft_isalpha(int c) 18 | { 19 | if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122)) 20 | return (1); 21 | return (0); 22 | } 23 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_isascii.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_isascii.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 10:52:34 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:25 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_isascii() checks whether c is a 7-bit unsigned char value that fits into 15 | the ASCII character set. 16 | */ 17 | 18 | int ft_isascii(int c) 19 | { 20 | if (c >= 0 && c <= 127) 21 | return (1); 22 | return (0); 23 | } 24 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_isdigit.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_isdigit.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 10:09:22 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:26 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_isdigit() checks for a digit (0 through 9). 15 | */ 16 | 17 | int ft_isdigit(int c) 18 | { 19 | if (c >= 48 && c <= 57) 20 | return (1); 21 | return (0); 22 | } 23 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_isprint.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_isprint.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 10:55:19 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:30 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_isprint() checks for any printable character including space. 15 | */ 16 | 17 | int ft_isprint(int c) 18 | { 19 | if (c >= 32 && c <= 126) 20 | return (1); 21 | return (0); 22 | } 23 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_isspace.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_isspace.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/15 14:29:13 by zelhajou #+# #+# */ 9 | /* Updated: 2024/02/18 16:41:44 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "libft.h" 14 | 15 | int ft_isspace(int c) 16 | { 17 | return (c == ' ' || c == '\t' || c == '\n' 18 | || c == '\v' || c == '\f' || c == '\r'); 19 | } 20 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_itoa.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_itoa.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/09 15:29:47 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/20 22:28:28 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Allocates (with malloc(3)) and returns a string representing 15 | the integer received as an argument. Negative numbers must be handled. 16 | 17 | n: the integer to convert. 18 | */ 19 | #include "libft.h" 20 | 21 | static int count_char(long n) 22 | { 23 | int i; 24 | 25 | i = 0; 26 | if (n == 0) 27 | return (1); 28 | else if (n < 0) 29 | { 30 | n *= -1; 31 | i++; 32 | } 33 | while (n > 0) 34 | { 35 | n = n / 10; 36 | i++; 37 | } 38 | return (i); 39 | } 40 | 41 | char *ft_itoa(int n) 42 | { 43 | int i; 44 | char *str; 45 | int number; 46 | long nb; 47 | 48 | i = 0; 49 | nb = n; 50 | number = count_char(n) - 1; 51 | str = (char *)ft_calloc((count_char(n) + 1), sizeof(char)); 52 | if (!str) 53 | return (NULL); 54 | if (n < 0) 55 | nb *= -1; 56 | while (number >= 0) 57 | { 58 | str[number] = (nb % 10) + '0'; 59 | nb = nb / 10; 60 | number--; 61 | i++; 62 | } 63 | if (n < 0) 64 | str[0] = '-'; 65 | return (str); 66 | } 67 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_lstadd_back.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_lstadd_back.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/17 18:53:42 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:28:37 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Adds the node ’new’ at the end of the list. 15 | 16 | lst: The address of a pointer to the first link of a list. 17 | new: The address of a pointer to the node to be added to the list. 18 | */ 19 | 20 | #include "libft.h" 21 | 22 | void ft_lstadd_back(t_list **lst, t_list *new) 23 | { 24 | t_list *pos; 25 | 26 | if (!new || !lst) 27 | return ; 28 | if (!*lst) 29 | { 30 | *lst = new; 31 | return ; 32 | } 33 | pos = ft_lstlast(*lst); 34 | pos->next = new; 35 | } 36 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_lstadd_front.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_lstadd_front.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/14 22:50:11 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:26:00 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Adds the node ’new’ at the beginning of the list. 15 | 16 | lst: The address of a pointer to the first link of a list. 17 | new: The address of a pointer to the node to be added to the list. 18 | */ 19 | 20 | #include "libft.h" 21 | 22 | void ft_lstadd_front(t_list **lst, t_list *new) 23 | { 24 | if (!new) 25 | return ; 26 | if (!lst) 27 | { 28 | *lst = new; 29 | return ; 30 | } 31 | new->next = *lst; 32 | *lst = new; 33 | } 34 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_lstclear.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_lstclear.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/17 21:11:10 by zelhajou #+# #+# */ 9 | /* Updated: 2024/02/15 11:19:57 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Deletes and frees the given node and every successor of that 15 | node, using the function ’del’ and free(3). Finally, the pointer to the 16 | list must be set to NULL. 17 | 18 | lst: The address of a pointer to a node. 19 | del: The address of the function used to delete the content of the node. 20 | */ 21 | 22 | #include "libft.h" 23 | 24 | void ft_lstclear(t_list **lst, void (*del)(void*)) 25 | { 26 | t_list *ptr; 27 | 28 | if (!*lst) 29 | return ; 30 | while (*lst) 31 | { 32 | ptr = (*lst)->next; 33 | ft_lstdelone(*lst, del); 34 | *lst = ptr; 35 | } 36 | *lst = 0; 37 | } 38 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_lstdelone.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_lstdelone.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/17 20:31:28 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:29:25 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Takes as a parameter a node and frees the memory of 15 | the node’s content using the function ’del’ given as a parameter and free 16 | the node. The memory of ’next’ must not be freed. 17 | 18 | lst: The node to free. 19 | del: The address of the function used to delete the content. 20 | */ 21 | 22 | #include "libft.h" 23 | 24 | void ft_lstdelone(t_list *lst, void (*del)(void*)) 25 | { 26 | if (!lst) 27 | return ; 28 | del(lst->content); 29 | free(lst); 30 | } 31 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_lstiter.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_lstiter.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/19 21:35:26 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:37:08 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Iterates the list ’lst’ and applies the function ’f’ on 15 | the content of each node. 16 | 17 | lst: The address of a pointer to a node. 18 | f: The address of the function used to iterate on the list. 19 | */ 20 | 21 | #include "libft.h" 22 | 23 | void ft_lstiter(t_list *lst, void (*f)(void *)) 24 | { 25 | if (!lst || !f) 26 | return ; 27 | while (lst) 28 | { 29 | f(lst->content); 30 | lst = lst->next; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_lstlast.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_lstlast.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/17 17:50:53 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:27:37 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Returns the last node of the list. 15 | 16 | lst: The beginning of the list. 17 | */ 18 | 19 | #include "libft.h" 20 | 21 | t_list *ft_lstlast(t_list *lst) 22 | { 23 | if (!lst) 24 | return (NULL); 25 | while (lst->next) 26 | lst = lst->next; 27 | return (lst); 28 | } 29 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_lstnew.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_lstnew.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/14 15:00:21 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:23:23 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Allocates (with malloc(3)) and returns a new node. The member 15 | variable ’content’ is initialized with the value of the parameter ’content’. 16 | The variable ’next’ is initialized to NULL. 17 | 18 | content: The content to create the node with. 19 | */ 20 | 21 | #include "libft.h" 22 | 23 | t_list *ft_lstnew(void *content) 24 | { 25 | t_list *new; 26 | 27 | new = (t_list *)malloc(sizeof(t_list)); 28 | if (!new) 29 | return (NULL); 30 | new->content = content; 31 | new->next = NULL; 32 | return (new); 33 | } 34 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_lstsize.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_lstsize.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/17 17:21:19 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:27:04 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Counts the number of nodes in a list. 15 | 16 | lst: The beginning of the list. 17 | */ 18 | 19 | #include "libft.h" 20 | 21 | int ft_lstsize(t_list *lst) 22 | { 23 | int i; 24 | 25 | i = 0; 26 | while (lst) 27 | { 28 | lst = lst->next; 29 | i++; 30 | } 31 | return (i); 32 | } 33 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_memchr.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_memchr.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/20 03:55:53 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:49 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_memchr() scans the initial n bytes of the memory area pointed to by s 15 | for the first instance of c. Both c and the bytes of the memory area 16 | pointed to by s are interpreted as unsigned char. 17 | */ 18 | 19 | #include "libft.h" 20 | 21 | void *ft_memchr(const void *s, int c, size_t n) 22 | { 23 | size_t i; 24 | unsigned char *obj; 25 | 26 | i = 0; 27 | obj = (unsigned char *)s; 28 | while (i < n) 29 | { 30 | if (obj[i] == (unsigned char)c) 31 | return (&obj[i]); 32 | i++; 33 | } 34 | return (0); 35 | } 36 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_memcmp.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_memcmp.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/22 01:13:29 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:50 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | The memcmp() function compares the first n bytes (each interpreted 15 | as unsigned char) of the memory areas s1 and s2. 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | int ft_memcmp(const void *s1, const void *s2, size_t n) 21 | { 22 | size_t i; 23 | unsigned char *obj1; 24 | unsigned char *obj2; 25 | 26 | i = 0; 27 | obj1 = (unsigned char *)s1; 28 | obj2 = (unsigned char *)s2; 29 | while (i < n) 30 | { 31 | if (obj1[i] != obj2[i]) 32 | return (obj1[i] - obj2[i]); 33 | i++; 34 | } 35 | return (0); 36 | } 37 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_memcpy.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_memcpy.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/20 19:31:40 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/21 03:30:39 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_memcpy() function copies n bytes from memory area src to memory area dest 15 | */ 16 | 17 | #include "libft.h" 18 | 19 | void *ft_memcpy(void *dst, const void *src, size_t n) 20 | { 21 | size_t i; 22 | unsigned char *s1; 23 | unsigned char *s2; 24 | 25 | i = 0; 26 | if (!dst && !src) 27 | return (0); 28 | s1 = (unsigned char *)dst; 29 | s2 = (unsigned char *)src; 30 | if (s1 == s2) 31 | return (s1); 32 | while (i < n) 33 | { 34 | s1[i] = s2[i]; 35 | i++; 36 | } 37 | return (s1); 38 | } 39 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_memmove.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_memmove.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/21 22:55:32 by zelhajou #+# #+# */ 9 | /* Updated: 2024/02/15 11:20:05 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_memmove() copies len bytes from string src to string dst. The two strings 15 | may overlap; the copy is always done in a non-destructive manner. 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | void *ft_memmove(void *dst, const void *src, size_t len) 21 | { 22 | unsigned char *s1; 23 | unsigned char *s2; 24 | 25 | s1 = (unsigned char *)src; 26 | s2 = (unsigned char *)dst; 27 | if (dst <= src) 28 | dst = ft_memcpy(dst, src, len); 29 | else 30 | { 31 | while (len--) 32 | s2[len] = s1[len]; 33 | } 34 | return (dst); 35 | } 36 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_memset.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_memset.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/18 15:28:07 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:42:55 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_memset() sets the first len bytes of the memory area pointed to by 15 | s to the value specified by c 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | void *ft_memset(void *s, int c, size_t n) 21 | { 22 | size_t i; 23 | unsigned char *obj; 24 | 25 | i = 0; 26 | obj = (unsigned char *)s; 27 | while (i < n) 28 | { 29 | obj[i] = (unsigned char)c; 30 | i++; 31 | } 32 | return (obj); 33 | } 34 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_putchar_fd.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_putchar_fd.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/03 23:11:51 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:18:35 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Outputs the character ’c’ to the given file descriptor. 15 | 16 | c: The character to output. 17 | fd: The file descriptor on which to write. 18 | */ 19 | 20 | #include "libft.h" 21 | 22 | void ft_putchar_fd(char c, int fd) 23 | { 24 | write(fd, &c, 1); 25 | } 26 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_putendl_fd.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_putendl_fd.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/05 02:54:59 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:20:50 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Outputs the string ’s’ to the given file descriptor followed 15 | by a newline. 16 | 17 | s: The string to output. 18 | fd: The file descriptor on which to write. 19 | */ 20 | 21 | #include "libft.h" 22 | 23 | void ft_putendl_fd(char *s, int fd) 24 | { 25 | ft_putstr_fd(s, fd); 26 | ft_putchar_fd('\n', fd); 27 | } 28 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_putnbr_fd.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_putnbr_fd.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/05 03:19:24 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:22:16 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Outputs the integer ’n’ to the given file descriptor. 15 | 16 | n: The integer to output. 17 | fd: The file descriptor on which to write. 18 | */ 19 | 20 | #include "libft.h" 21 | 22 | void ft_putnbr_fd(int n, int fd) 23 | { 24 | long long nbr; 25 | 26 | nbr = n; 27 | if (nbr < 0) 28 | { 29 | ft_putchar_fd('-', fd); 30 | nbr = nbr * -1; 31 | } 32 | if (nbr > 9) 33 | ft_putnbr_fd((nbr / 10), fd); 34 | write(fd, &"0123456789"[nbr % 10], 1); 35 | } 36 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_putstr_fd.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_putstr_fd.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/05 02:22:59 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:19:27 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Outputs the string ’s’ to the given file descriptor. 15 | 16 | s: The string to output. 17 | fd: The file descriptor on which to write. 18 | */ 19 | 20 | #include "libft.h" 21 | 22 | void ft_putstr_fd(char *s, int fd) 23 | { 24 | while (*s != '\0') 25 | { 26 | ft_putchar_fd(*s, fd); 27 | s++; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_split.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_split.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/01 11:06:01 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:09:52 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Allocates (with malloc(3)) and returns an array of strings 15 | obtained by splitting ’s’ using the character ’c’ as a delimiter. 16 | The array must end with a NULL pointer. 17 | 18 | s: The string to be split. 19 | c: The delimiter character. 20 | */ 21 | 22 | #include "libft.h" 23 | 24 | static char **ft_free(char **str) 25 | { 26 | int i; 27 | 28 | i = 0; 29 | while (str[i]) 30 | { 31 | free (str[i]); 32 | i++; 33 | } 34 | free (str); 35 | str = NULL; 36 | return (str); 37 | } 38 | 39 | static int count_word(char const *s, char c) 40 | { 41 | int i; 42 | int j; 43 | int flag; 44 | 45 | i = 0; 46 | j = 0; 47 | flag = 0; 48 | while (s[i]) 49 | { 50 | if (s[i] != c && flag == 0) 51 | { 52 | j++; 53 | flag = 1; 54 | } 55 | else if (s[i] == c && flag == 1) 56 | flag = 0; 57 | i++; 58 | } 59 | return (j); 60 | } 61 | 62 | static int count_char(char const *s, char c) 63 | { 64 | int i; 65 | int j; 66 | 67 | i = 0; 68 | j = 0; 69 | while (s[i]) 70 | { 71 | if (s[j] != c) 72 | j++; 73 | i++; 74 | } 75 | return (j); 76 | } 77 | 78 | char **ft_split(char const *s, char c) 79 | { 80 | int i; 81 | char **ptr; 82 | int number_word; 83 | int number_char; 84 | 85 | i = 0; 86 | number_char = 0; 87 | if (!s) 88 | return (NULL); 89 | number_word = count_word(s, c); 90 | ptr = (char **)malloc(sizeof(char *) * (number_word + 1)); 91 | if (!ptr) 92 | return (NULL); 93 | while (i < number_word) 94 | { 95 | while (*s == c) 96 | s++; 97 | number_char = count_char(s, c); 98 | ptr[i] = ft_substr(s, 0, number_char); 99 | if (!ptr[i]) 100 | ptr = ft_free(ptr); 101 | s += number_char; 102 | i++; 103 | } 104 | return (ptr[i] = NULL, ptr); 105 | } 106 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strchr.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strchr.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 11:45:21 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:08 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_strchr() returns a pointer to the first occurrence 15 | of the character c in the string s. 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | char *ft_strchr(const char *s, int c) 21 | { 22 | while (*s != '\0') 23 | { 24 | if (*s == (char)c) 25 | return ((char *)s); 26 | s++; 27 | } 28 | if (*s == (char)c) 29 | return ((char *)s); 30 | return (0); 31 | } 32 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strdup.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strdup.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/27 15:03:07 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:10 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | strdup() returns a pointer to a new string which is a duplicate 15 | of the string s. Memory for the new string is obtained with malloc. 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | char *ft_strdup(const char *src) 21 | { 22 | size_t i; 23 | size_t size; 24 | char *str; 25 | 26 | i = 0; 27 | size = ft_strlen(src); 28 | str = malloc(size + 1); 29 | if (str == NULL) 30 | return (NULL); 31 | while (src[i]) 32 | { 33 | str[i] = src[i]; 34 | i++; 35 | } 36 | str[i] = '\0'; 37 | return (str); 38 | } 39 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_striteri.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_striteri.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/06 03:26:49 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/21 03:05:32 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Applies the function ’f’ on each character of the string 15 | passed as argument, passing its index as first argument. 16 | Each character is passed by address to ’f’ to be modified if necessary. 17 | 18 | s: The string on which to iterate. 19 | f: The function to apply to each character. 20 | */ 21 | 22 | #include "libft.h" 23 | 24 | void ft_striteri(char *s, void (*f)(unsigned int, char*)) 25 | { 26 | int i; 27 | 28 | i = 0; 29 | if (!s || !f) 30 | return ; 31 | while (s[i]) 32 | { 33 | f(i, &(s[i])); 34 | i++; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strjoin.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strjoin.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/27 18:11:35 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:06:18 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Allocates (with malloc(3)) and returns a new string, 15 | which is the result of the concatenation of ’s1’ and ’s2’. 16 | 17 | s1: The prefix string. 18 | s2: The suffix string. 19 | */ 20 | 21 | #include "libft.h" 22 | 23 | char *ft_strjoin(char const *s1, char const *s2) 24 | { 25 | size_t len; 26 | char *str; 27 | size_t i; 28 | size_t j; 29 | 30 | i = 0; 31 | j = -1; 32 | if (!s1 || !s2) 33 | return (NULL); 34 | len = ft_strlen(s1) + ft_strlen(s2); 35 | str = (char *)malloc(sizeof(char) * (len + 1)); 36 | if (!str) 37 | return (NULL); 38 | while (len--) 39 | { 40 | if (s1[i]) 41 | { 42 | str[i] = s1[i]; 43 | i++; 44 | } 45 | else if (s2[++j]) 46 | str[i + j] = s2[j]; 47 | } 48 | str[i + j + 1] = '\0'; 49 | return (str); 50 | } 51 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strlcat.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strlcat.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/22 00:00:07 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:16 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_strlcat() appends the NUL-terminated string src to the end of dst.It will 15 | append at most size - strlen(dst) - 1 bytes, NUL-terminating the result. 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | size_t ft_strlcat(char *dst, const char *src, size_t dstsize) 21 | { 22 | size_t i; 23 | size_t j; 24 | 25 | i = 0; 26 | while (i < dstsize && *dst) 27 | { 28 | dst++; 29 | i++; 30 | } 31 | if (i == dstsize) 32 | return (i + ft_strlen(src)); 33 | j = 0; 34 | while (src[j]) 35 | { 36 | if (j < dstsize - i - 1) 37 | *dst ++ = src[j]; 38 | j++; 39 | } 40 | *dst = '\0'; 41 | return (i + j); 42 | } 43 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strlcpy.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strlcpy.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/20 22:29:54 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:18 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_strlcpy() copies up to size - 1 characters from the NUL-terminated 15 | string src to dst, NUL-terminating the result. 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | size_t ft_strlcpy(char *dst, const char *src, size_t size) 21 | { 22 | size_t i; 23 | size_t len; 24 | 25 | i = 0; 26 | len = ft_strlen(src); 27 | if (size == 0) 28 | return (len); 29 | while (src[i] != '\0' && i < size - 1) 30 | { 31 | dst[i] = src[i]; 32 | i++; 33 | } 34 | dst[i] = '\0'; 35 | return (len); 36 | } 37 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strlen.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strlen.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/21 04:42:01 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:20 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | strlen() - calculate the length of a string 15 | */ 16 | 17 | #include "libft.h" 18 | 19 | size_t ft_strlen(const char *s) 20 | { 21 | size_t i; 22 | 23 | i = 0; 24 | while (s[i] != '\0') 25 | i++; 26 | return (i); 27 | } 28 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strmapi.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strmapi.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/11/06 01:03:10 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/21 02:54:27 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Applies the function ’f’ to each character of the string ’s’, 15 | and passing its index as first argument to create a new string 16 | (with malloc(3)) resulting from successive applications of ’f’. 17 | 18 | s: The string on which to iterate. 19 | f: The function to apply to each character. 20 | */ 21 | 22 | #include "libft.h" 23 | 24 | char *ft_strmapi(char const *s, char (*f)(unsigned int, char)) 25 | { 26 | int i; 27 | char *str; 28 | 29 | if (!s || !f) 30 | return (0); 31 | i = 0; 32 | str = malloc(sizeof(char) * ft_strlen(s) + 1); 33 | if (!str) 34 | return (NULL); 35 | while (s[i]) 36 | { 37 | str[i] = f(i, s[i]); 38 | i++; 39 | } 40 | str[i] = '\0'; 41 | return (str); 42 | } 43 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strncmp.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strncmp.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 15:38:34 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:25 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_strcmp() compares the two strings s1 and s2. It returns an integer less 15 | than, equal to, or greater than zero if s1 is found, respectively, 16 | to be less than, to match, or be greater than s2. 17 | 18 | ft_strncmp() is similar, except it only compares the first (at most) n bytes 19 | of s1 and s2. 20 | */ 21 | 22 | #include "libft.h" 23 | 24 | int ft_strncmp(const char *s1, const char *s2, size_t n) 25 | { 26 | size_t i; 27 | 28 | i = 0; 29 | while ((s1[i] != '\0' || s2[i] != '\0') && i < n) 30 | { 31 | if (s1[i] != s2[i]) 32 | return ((unsigned char)s1[i] - (unsigned char)s2[i]); 33 | i++; 34 | } 35 | return (0); 36 | } 37 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strndup.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strndup.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/14 16:13:17 by zelhajou #+# #+# */ 9 | /* Updated: 2024/02/14 16:15:37 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "libft.h" 14 | 15 | char *ft_strndup(const char *src, size_t n) 16 | { 17 | size_t i; 18 | size_t size; 19 | char *str; 20 | 21 | i = 0; 22 | size = ft_strnlen(src, n); 23 | str = malloc(size + 1); 24 | if (str == NULL) 25 | return (NULL); 26 | while (i < size) 27 | { 28 | str[i] = src[i]; 29 | i++; 30 | } 31 | str[i] = '\0'; 32 | return (str); 33 | } 34 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strnlen.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strnlen.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/14 16:11:42 by zelhajou #+# #+# */ 9 | /* Updated: 2024/02/14 16:17:24 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "libft.h" 14 | 15 | size_t ft_strnlen(const char *s, size_t maxlen) 16 | { 17 | size_t len; 18 | 19 | len = 0; 20 | while (len < maxlen && s[len]) 21 | len++; 22 | return (len); 23 | } 24 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strnstr.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strnstr.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/26 11:03:39 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:27 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_strnstr() Find the first substring in a length-limited string 15 | big: The string to be searched 16 | little: The string to search for 17 | len: the maximum number of characters to search 18 | */ 19 | 20 | #include "libft.h" 21 | 22 | char *ft_strnstr(const char *big, const char *little, size_t len) 23 | { 24 | size_t i; 25 | size_t j; 26 | 27 | i = 0; 28 | if (little[i] == '\0') 29 | return ((char *) big); 30 | while ((big[i] != '\0') && i < len) 31 | { 32 | j = 0; 33 | while (big[i + j] == little[j] && (i + j) < len) 34 | { 35 | if (little[j + 1] == '\0') 36 | return ((char *)big + i); 37 | j++; 38 | } 39 | i++; 40 | } 41 | return (0); 42 | } 43 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strrchr.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strrchr.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 16:29:24 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:29 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_strrchr() returns a pointer to the last occurrence 15 | of the character c in the string s 16 | */ 17 | 18 | #include "libft.h" 19 | 20 | char *ft_strrchr(const char *s, int c) 21 | { 22 | int size; 23 | 24 | size = ft_strlen(s); 25 | while (size >= 0) 26 | { 27 | if (s[size] == (char)c) 28 | return ((char *)s + size); 29 | size--; 30 | } 31 | return (0); 32 | } 33 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_strtrim.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_strtrim.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/28 07:48:23 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:08:41 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Descriptin : Allocates (with malloc(3)) and returns a copy of ’s1’ with the 15 | characters specified in ’set’ removed from the beginning and the end of 16 | the string. 17 | 18 | s1: The string to be trimmed. 19 | set: The reference set of characters to trim. 20 | */ 21 | 22 | #include "libft.h" 23 | 24 | static int first_set(const char *s1, const char *set) 25 | { 26 | int i; 27 | int c; 28 | int j; 29 | 30 | i = 0; 31 | while (s1[i] != '\0') 32 | { 33 | c = 0; 34 | j = 0; 35 | while (set[j] != '\0') 36 | { 37 | if (set[j] == s1[i]) 38 | c++; 39 | j++; 40 | } 41 | if (c == 0) 42 | return (i); 43 | i++; 44 | } 45 | return (i); 46 | } 47 | 48 | static int last_set(const char *s1, const char *set) 49 | { 50 | int c; 51 | int j; 52 | int len; 53 | 54 | len = ft_strlen(s1); 55 | while (len--) 56 | { 57 | c = 0; 58 | j = 0; 59 | while (set[j] != '\0') 60 | { 61 | if (set[j] == s1[len]) 62 | c++; 63 | j++; 64 | } 65 | if (c == 0) 66 | return (len); 67 | } 68 | return (len); 69 | } 70 | 71 | char *ft_strtrim(char const *s1, char const *set) 72 | { 73 | char *ptr; 74 | int i; 75 | int first; 76 | int last; 77 | 78 | i = 0; 79 | if (!s1) 80 | return (NULL); 81 | first = first_set(s1, set); 82 | last = last_set(s1, set); 83 | if (first > last) 84 | return (ft_strdup("")); 85 | ptr = (char *)malloc(sizeof(char) * ((last - first) + 2)); 86 | if (ptr == NULL) 87 | return (NULL); 88 | while (first <= last) 89 | { 90 | ptr[i] = s1[first]; 91 | first++; 92 | i++; 93 | } 94 | ptr[i] = '\0'; 95 | return (ptr); 96 | } 97 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_substr.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_substr.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/27 15:41:59 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 21:06:13 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | Description : Allocates (with malloc(3)) and returns a substring from 15 | the string ’s’. The substring begins at index ’start’ and is of 16 | maximum size ’len’. 17 | 18 | s: The string from which to create the substring. 19 | start: The start index of the substring in the string ’s’. 20 | len: The maximum length of the substring. 21 | */ 22 | 23 | #include "libft.h" 24 | 25 | char *ft_substr(char const *s, unsigned int start, size_t len) 26 | { 27 | unsigned int i; 28 | size_t j; 29 | char *substr; 30 | 31 | i = -1; 32 | j = 0; 33 | if (!s) 34 | return (NULL); 35 | if (start >= ft_strlen(s)) 36 | return (ft_strdup("")); 37 | if (len >= ft_strlen(s)) 38 | substr = (char *)malloc(sizeof(char) * (ft_strlen(s) + 1)); 39 | else 40 | substr = (char *)malloc(sizeof(char) * (len + 1)); 41 | if (!substr) 42 | return (NULL); 43 | while (s[++i]) 44 | { 45 | if (i >= start && j < len) 46 | substr[j++] = s[i]; 47 | } 48 | substr[j] = '\0'; 49 | return (substr); 50 | } 51 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_tolower.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_tolower.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 11:11:15 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:35 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_tolower() converts the letter c to lower case, if possible. 15 | */ 16 | 17 | int ft_tolower(int c) 18 | { 19 | if (c >= 'A' && c <= 'Z') 20 | return (c + 32); 21 | return (c); 22 | } 23 | -------------------------------------------------------------------------------- /minishell/lib/libft/ft_toupper.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_toupper.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/17 10:59:51 by zelhajou #+# #+# */ 9 | /* Updated: 2022/11/19 20:43:37 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | /* 14 | ft_toupper() converts the letter c to upper case, if possible. 15 | */ 16 | 17 | int ft_toupper(int c) 18 | { 19 | if (c >= 'a' && c <= 'z') 20 | return (c - 32); 21 | return (c); 22 | } 23 | -------------------------------------------------------------------------------- /minishell/lib/libft/libft.h: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* libft.h :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2022/10/19 22:53:36 by zelhajou #+# #+# */ 9 | /* Updated: 2024/02/15 14:31:36 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef LIBFT_H 14 | # define LIBFT_H 15 | 16 | # include 17 | # include 18 | # include 19 | # include 20 | # include 21 | 22 | /* Part 1 - Libc functions */ 23 | 24 | /* ----------------------------- ------------------------------ */ 25 | 26 | int ft_isalpha(int c); 27 | int ft_isdigit(int c); 28 | int ft_isalnum(int c); 29 | int ft_isascii(int c); 30 | int ft_isprint(int c); 31 | int ft_tolower(int c); 32 | int ft_toupper(int c); 33 | int ft_isspace(int c); 34 | 35 | /* ----------------------------- ----------------------------- */ 36 | 37 | size_t ft_strlen(const char *s); 38 | size_t ft_strnlen(const char *s, size_t maxlen); 39 | char *ft_strchr(const char *s, int c); 40 | char *ft_strrchr(const char *s, int c); 41 | char *ft_strnstr(const char *big, const char *little, size_t len); 42 | int ft_strncmp(const char *s1, const char *s2, size_t n); 43 | size_t ft_strlcpy(char *dst, const char *src, size_t size); 44 | size_t ft_strlcat(char *dst, const char *src, size_t dstsize); 45 | 46 | // Memory Functions 47 | void ft_bzero(void *s, size_t n); 48 | int ft_memcmp(const void *s1, const void *s2, size_t n); 49 | void *ft_memchr(const void *s, int c, size_t n); 50 | void *ft_memset(void *s, int c, size_t n); 51 | void *ft_memcpy(void *dst, const void *src, size_t n); 52 | void *ft_memmove(void *dst, const void *src, size_t len); 53 | 54 | /* ----------------------------- ----------------------------- */ 55 | 56 | int ft_atoi(const char *str); 57 | void *ft_calloc(size_t nmemb, size_t size); 58 | char *ft_strdup(const char *s); 59 | char *ft_strndup(const char *src, size_t n); 60 | 61 | /* Part 2 - Additional functions */ 62 | 63 | char *ft_substr(char const *s, unsigned int start, size_t len); 64 | char *ft_strjoin(char const *s1, char const *s2); 65 | char *ft_strtrim(char const *s1, char const *set); 66 | char **ft_split(char const *s, char c); 67 | char *ft_itoa(int n); 68 | char *ft_strmapi(char const *s, char (*f)(unsigned int, char)); 69 | void ft_striteri(char *s, void (*f)(unsigned int, char*)); 70 | void ft_putchar_fd(char c, int fd); 71 | void ft_putstr_fd(char *s, int fd); 72 | void ft_putendl_fd(char *s, int fd); 73 | void ft_putnbr_fd(int n, int fd); 74 | 75 | /* Bonus Part */ 76 | typedef struct s_list 77 | { 78 | void *content; 79 | struct s_list *next; 80 | } t_list; 81 | 82 | t_list *ft_lstnew(void *content); 83 | void ft_lstadd_front(t_list **lst, t_list *new); 84 | int ft_lstsize(t_list *lst); 85 | t_list *ft_lstlast(t_list *lst); 86 | void ft_lstadd_back(t_list **lst, t_list *new); 87 | void ft_lstdelone(t_list *lst, void (*del)(void*)); 88 | void ft_lstclear(t_list **lst, void (*del)(void*)); 89 | void ft_lstiter(t_list *lst, void (*f)(void *)); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /minishell/src/01_input_validation/syntax_checker.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* syntax_checker.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/14 17:56:51 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/02 17:28:26 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int syntax_error_checker(const char *input) 16 | { 17 | if (has_unclosed_quotes(input)) 18 | { 19 | ft_putstr_fd("Syntax error: unclosed quote\n", STDERR_FILENO); 20 | return (1); 21 | } 22 | if (has_invalid_redirections(input)) 23 | { 24 | ft_putstr_fd("Syntax error: invalid redirection\n", STDERR_FILENO); 25 | return (1); 26 | } 27 | if (has_misplaced_operators(input)) 28 | { 29 | ft_putstr_fd("Syntax error: misplaced operator\n", STDERR_FILENO); 30 | return (1); 31 | } 32 | if (has_logical_operators(input)) 33 | { 34 | ft_putstr_fd("Error: Logical operators '&&' and '||' \ 35 | are not supported.\n", STDERR_FILENO); 36 | return (1); 37 | } 38 | return (0); 39 | } 40 | 41 | int has_unclosed_quotes(const char *input) 42 | { 43 | char quote_type; 44 | 45 | quote_type = 0; 46 | while (*input) 47 | { 48 | if (*input == '\'' || *input == '\"') 49 | { 50 | if (quote_type == *input) 51 | quote_type = 0; 52 | else if (!quote_type) 53 | quote_type = *input; 54 | } 55 | input++; 56 | } 57 | return (quote_type != 0); 58 | } 59 | 60 | int has_invalid_redirections(const char *input) 61 | { 62 | int s_q_count; 63 | int d_q_count; 64 | 65 | s_q_count = 0; 66 | d_q_count = 0; 67 | while (*input) 68 | { 69 | update_quote_counts(*input, &s_q_count, &d_q_count); 70 | if ((!(s_q_count % 2) && !(d_q_count % 2)) 71 | && (*input == '>' || *input == '<')) 72 | { 73 | if (is_invalid_operator(&input)) 74 | return (1); 75 | } 76 | else 77 | input++; 78 | } 79 | return (0); 80 | } 81 | 82 | int has_misplaced_operators(const char *input) 83 | { 84 | int expect_command_next; 85 | int s_q_count; 86 | int d_q_count; 87 | 88 | s_q_count = 0; 89 | d_q_count = 0; 90 | expect_command_next = 0; 91 | if (*input == '|' || *input == '&') 92 | return (1); 93 | while (*input) 94 | { 95 | update_quote_counts(*input, &s_q_count, &d_q_count); 96 | if (*input == '|' && !(s_q_count % 2) && !(d_q_count % 2)) 97 | { 98 | if (expect_command_next) 99 | return (1); 100 | expect_command_next = 1; 101 | } 102 | else if (!ft_isspace(*input)) 103 | expect_command_next = 0; 104 | input++; 105 | } 106 | if (expect_command_next) 107 | return (1); 108 | return (0); 109 | } 110 | 111 | int has_logical_operators(const char *input) 112 | { 113 | int s_q_count; 114 | int d_q_count; 115 | 116 | s_q_count = 0; 117 | d_q_count = 0; 118 | while (*input) 119 | { 120 | update_quote_counts(*input, &s_q_count, &d_q_count); 121 | if (!(d_q_count % 2) && !(s_q_count % 2) 122 | && ((*input == '&' && *(input + 1) == '&') 123 | || (*input == '|' && *(input + 1) == '|'))) 124 | return (1); 125 | input++; 126 | } 127 | return (0); 128 | } 129 | -------------------------------------------------------------------------------- /minishell/src/01_input_validation/syntax_checker_utils.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* syntax_checker_utils.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/03/02 00:15:54 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/02 17:43:21 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void update_quote_counts(char c, int *s_q_count, int *d_q_count) 16 | { 17 | if (c == 34) 18 | (*d_q_count)++; 19 | else if (c == 39) 20 | (*s_q_count)++; 21 | } 22 | 23 | const char *skip_spaces(const char *input) 24 | { 25 | while (*input && (*input == ' ' || *input == '\t')) 26 | input++; 27 | return (input); 28 | } 29 | 30 | int is_invalid_operator(const char **input) 31 | { 32 | const char *operator_start; 33 | 34 | operator_start = *input; 35 | (*input)++; 36 | if (*operator_start == **input) 37 | (*input)++; 38 | *input = skip_spaces(*input); 39 | if (**input == '\0' || **input == '>' 40 | || **input == '<' || **input == '|') 41 | return (1); 42 | return (0); 43 | } 44 | -------------------------------------------------------------------------------- /minishell/src/02_tokenization/print_tokens.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* print_tokens.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/03/02 17:47:19 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/05 16:10:18 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | // const char *get_token_type_name(t_token_type type) 16 | // { 17 | // const char *token_type_names[7]; 18 | 19 | // token_type_names[0] = "WORD"; 20 | // token_type_names[1] = "PIPE"; 21 | // token_type_names[2] = "REDIRECT_IN"; 22 | // token_type_names[3] = "REDIRECT_OUT"; 23 | // token_type_names[4] = "REDIRECT_APPEND"; 24 | // token_type_names[5] = "REDIRECT_HEREDOC"; 25 | // token_type_names[6] = "TOKEN_ENV_VAR"; 26 | // if (type >= 0 && type < 7) 27 | // return (token_type_names[type]); 28 | // return ("UNKNOWN"); 29 | // } 30 | 31 | // void display_tokens(t_token *tokens) 32 | // { 33 | // t_token *token; 34 | 35 | // token = tokens; 36 | // while (token) 37 | // { 38 | // printf("Token: \033[0;36m %-20s \033[0m |\t \ 39 | // Type: \033[0;35m %-18s \033[0m \n", 40 | // token->value, get_token_type_name(token->type)); 41 | // printf("--------------------------------------------------\n"); 42 | // token = token->next; 43 | // } 44 | // } -------------------------------------------------------------------------------- /minishell/src/02_tokenization/tokenizer.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* tokenizer.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/15 14:26:48 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/02 17:44:51 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void handle_special_chars(char **input, t_token **tokens) 16 | { 17 | if (**input == '>') 18 | { 19 | if (*(*input + 1) == '>') 20 | { 21 | add_token_to_list(tokens, new_token(TOKEN_REDIR_APPEND, ">>")); 22 | (*input)++; 23 | } 24 | else 25 | add_token_to_list(tokens, new_token(TOKEN_REDIR_OUT, ">")); 26 | } 27 | else if (**input == '<') 28 | { 29 | if (*(*input + 1) == '<') 30 | { 31 | add_token_to_list(tokens, new_token(TOKEN_REDIR_HEREDOC, "<<")); 32 | (*input)++; 33 | } 34 | else 35 | add_token_to_list(tokens, new_token(TOKEN_REDIR_IN, "<")); 36 | } 37 | else if (**input == '|') 38 | add_token_to_list(tokens, new_token(TOKEN_PIPE, "|")); 39 | (*input)++; 40 | } 41 | 42 | void handle_word(char **input, t_token **tokens) 43 | { 44 | char *start; 45 | int in_quote; 46 | char quote_char; 47 | 48 | start = *input; 49 | in_quote = 0; 50 | quote_char = '\0'; 51 | while (**input) 52 | { 53 | update_quote_status(**input, &in_quote, "e_char); 54 | if (!in_quote && ft_strchr(" \t\n><|", **input)) 55 | break ; 56 | (*input)++; 57 | } 58 | add_word_token_if_valid(&start, input, tokens); 59 | } 60 | 61 | t_token *tokenize_input(char *input) 62 | { 63 | t_token *tokens; 64 | 65 | tokens = NULL; 66 | while (*input) 67 | { 68 | while (*input && ft_strchr(" \t\n", *input)) 69 | input++; 70 | if (ft_strchr("><|", *input)) 71 | handle_special_chars(&input, &tokens); 72 | else 73 | handle_word(&input, &tokens); 74 | } 75 | return (tokens); 76 | } 77 | -------------------------------------------------------------------------------- /minishell/src/02_tokenization/tokenizer_utils.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* tokenizer_utils.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/18 16:56:46 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/02 17:43:50 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | t_token *new_token(t_token_type type, char *value) 16 | { 17 | t_token *token; 18 | 19 | token = malloc(sizeof(t_token)); 20 | if (!token) 21 | return (NULL); 22 | token->type = type; 23 | token->value = ft_strdup(value); 24 | if (!token->value) 25 | { 26 | free(token); 27 | return (NULL); 28 | } 29 | token->next = NULL; 30 | return (token); 31 | } 32 | 33 | void add_token_to_list(t_token **tokens, t_token *new_token) 34 | { 35 | t_token *last; 36 | 37 | if (!*tokens) 38 | *tokens = new_token; 39 | else 40 | { 41 | last = *tokens; 42 | while (last->next) 43 | last = last->next; 44 | last->next = new_token; 45 | } 46 | } 47 | 48 | void free_tokens(t_token *tokens) 49 | { 50 | t_token *tmp; 51 | 52 | while (tokens) 53 | { 54 | tmp = tokens; 55 | tokens = tokens->next; 56 | free(tmp->value); 57 | free(tmp); 58 | } 59 | } 60 | 61 | void update_quote_status(char c, int *in_quote, char *quote_char) 62 | { 63 | if (!*in_quote && (c == '\'' || c == '\"')) 64 | { 65 | *in_quote = 1; 66 | *quote_char = c; 67 | } 68 | else if (*in_quote && c == *quote_char) 69 | *in_quote = 0; 70 | } 71 | 72 | void add_word_token_if_valid(char **start, char **input, t_token **tokens) 73 | { 74 | char *word; 75 | 76 | if (*input > *start) 77 | { 78 | word = ft_strndup(*start, *input - *start); 79 | if (word) 80 | { 81 | add_token_to_list(tokens, new_token(TOKEN_WORD, word)); 82 | free(word); 83 | } 84 | else 85 | ft_putstr_fd("Error: Malloc failed in handle_word.\n", 2); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /minishell/src/03_parsing/parser.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* parser.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/12 11:43:46 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/06 12:43:20 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | t_ast_node *parse_command(t_token **tokens) 16 | { 17 | t_ast_node *command_node; 18 | int arg_count; 19 | 20 | command_node = new_ast_node(TOKEN_WORD); 21 | arg_count = count_command_arguments(*tokens); 22 | command_node->args = malloc(sizeof(char *) * (arg_count + 1)); 23 | if (!command_node->args) 24 | return (NULL); 25 | fill_command_arguments(command_node, tokens, arg_count); 26 | return (command_node); 27 | } 28 | 29 | t_ast_node *create_file_node(t_token *token) 30 | { 31 | t_ast_node *node; 32 | 33 | node = malloc(sizeof(t_ast_node)); 34 | if (!node) 35 | return (NULL); 36 | node->type = token->type; 37 | node->args = malloc(sizeof(char *) * 2); 38 | if (!node->args) 39 | { 40 | free(node); 41 | return (NULL); 42 | } 43 | node->args[0] = token->value; 44 | node->args[1] = NULL; 45 | node->left = NULL; 46 | node->right = NULL; 47 | free(token); 48 | return (node); 49 | } 50 | 51 | t_ast_node *parse_redirection(t_token **tokens) 52 | { 53 | t_token *tmp; 54 | t_ast_node *redirect_node; 55 | t_token *next_token; 56 | 57 | if (!*tokens) 58 | return (NULL); 59 | tmp = *tokens; 60 | if ((*tokens)->type >= TOKEN_REDIR_IN 61 | && (*tokens)->type <= TOKEN_REDIR_HEREDOC) 62 | return (create_and_link_redirection(tokens, tmp)); 63 | while (*tokens && (*tokens)->next) 64 | { 65 | next_token = (*tokens)->next; 66 | if ((*tokens)->next->type >= TOKEN_REDIR_IN 67 | && (*tokens)->next->type <= TOKEN_REDIR_HEREDOC) 68 | { 69 | redirect_node = new_ast_node((*tokens)->next->type); 70 | (*tokens)->next = next_token->next->next; 71 | redirect_node->left = parse_redirection(&tmp); 72 | redirect_node->right = create_file_node((next_token->next)); 73 | return (free(next_token->value), free(next_token), redirect_node); 74 | } 75 | *tokens = next_token; 76 | } 77 | return (parse_command(&tmp)); 78 | } 79 | 80 | t_ast_node *parse_pipeline(t_token **tokens) 81 | { 82 | t_token *tmp; 83 | t_token *next_token; 84 | t_ast_node *pipe_node; 85 | 86 | tmp = *tokens; 87 | while (*tokens && (*tokens)->next) 88 | { 89 | next_token = (*tokens)->next; 90 | if ((*tokens)->next->type == TOKEN_PIPE) 91 | { 92 | pipe_node = new_ast_node((*tokens)->next->type); 93 | (*tokens)->next = NULL; 94 | pipe_node->left = parse_redirection(&tmp); 95 | pipe_node->right = parse_pipeline(&(next_token->next)); 96 | free(next_token->value); 97 | free(next_token); 98 | return (pipe_node); 99 | } 100 | *tokens = next_token; 101 | } 102 | return (parse_redirection(&tmp)); 103 | } 104 | 105 | t_ast_node *parse_tokens(t_token **tokens) 106 | { 107 | if (!tokens || !*tokens) 108 | return (NULL); 109 | return (parse_pipeline(tokens)); 110 | } 111 | -------------------------------------------------------------------------------- /minishell/src/03_parsing/parser_utils.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* parser_utils.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/18 23:26:44 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/02 20:54:58 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | t_ast_node *new_ast_node(t_token_type type) 16 | { 17 | t_ast_node *node; 18 | 19 | node = malloc(sizeof(t_ast_node)); 20 | if (!node) 21 | return (NULL); 22 | node->type = type; 23 | node->args = NULL; 24 | node->left = NULL; 25 | node->right = NULL; 26 | return (node); 27 | } 28 | 29 | void free_ast(t_ast_node *node) 30 | { 31 | int i; 32 | 33 | i = 0; 34 | if (!node) 35 | return ; 36 | if (node->type == TOKEN_WORD && node->args) 37 | { 38 | while (node->args && node->args[i]) 39 | { 40 | free(node->args[i]); 41 | i++; 42 | } 43 | free(node->args); 44 | } 45 | free_ast(node->left); 46 | free_ast(node->right); 47 | free(node); 48 | } 49 | 50 | t_ast_node *create_and_link_redirection(t_token **tokens, t_token *tmp) 51 | { 52 | t_ast_node *redirect_node; 53 | 54 | redirect_node = new_ast_node((*tokens)->type); 55 | *tokens = (*tokens)->next->next; 56 | redirect_node->left = parse_redirection(tokens); 57 | redirect_node->right = create_file_node(tmp->next); 58 | free(tmp->value); 59 | free(tmp); 60 | return (redirect_node); 61 | } 62 | 63 | int count_command_arguments(t_token *current) 64 | { 65 | int arg_count; 66 | 67 | arg_count = 0; 68 | while (current && current->type == TOKEN_WORD) 69 | { 70 | arg_count++; 71 | current = current->next; 72 | } 73 | return (arg_count); 74 | } 75 | 76 | void fill_command_arguments(t_ast_node *command_node, 77 | t_token **tokens, int arg_count) 78 | { 79 | int i; 80 | t_token *tmp; 81 | 82 | i = 0; 83 | while (i < arg_count) 84 | { 85 | command_node->args[i] = ft_strdup((*tokens)->value); 86 | tmp = *tokens; 87 | *tokens = (*tokens)->next; 88 | free(tmp->value); 89 | free(tmp); 90 | i++; 91 | } 92 | command_node->args[arg_count] = NULL; 93 | } 94 | -------------------------------------------------------------------------------- /minishell/src/04_execution/builtin_command_execution.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* builtin_command_execution.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:00:43 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:37:06 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int simple_child_for_builtins(char **_cmd_, int *_fd, t_env *env, int *_piped) 16 | { 17 | pid_t pid; 18 | int fd_[2]; 19 | int _out_fd_[2]; 20 | int status; 21 | 22 | (pipe(fd_), pid = fork()); 23 | if (!pid) 24 | { 25 | if (_piped[0] && _piped[0] <= _piped[5]) 26 | dup2(_fd[0], 0); 27 | if (_piped[0] > 1) 28 | dup2(fd_[1], 1); 29 | else 30 | close(_fd[0]); 31 | close_pipe_ends(fd_[0], fd_[1]); 32 | dup2(1, _out_fd_[1]); 33 | status = execute_builtin_command_in_child(_cmd_, env, _out_fd_, _piped); 34 | exit(WEXITSTATUS(status)); 35 | } 36 | close_pipe_ends(fd_[1], _fd[0]); 37 | if (_piped[0] > 1) 38 | _fd[0] = fd_[0]; 39 | else 40 | close(fd_[0]); 41 | return (1); 42 | } 43 | 44 | void exec_builtin_and_exit( 45 | char **_cmd_, t_env *env, int *_out_fd, int *_piped) 46 | { 47 | int status; 48 | 49 | status = execute_builtin_command_in_child( 50 | _cmd_, env, _out_fd, _piped); 51 | exit(WEXITSTATUS(status)); 52 | } 53 | 54 | int execute_child_with_redirections( 55 | char **_cmd_, int *_fd, t_env *env, int *_piped) 56 | { 57 | pid_t pid; 58 | int _out_fd[2]; 59 | 60 | _out_fd[1] = 1; 61 | if (_piped[8] && _piped[7]) 62 | _out_fd[1] = _piped[2]; 63 | if (_piped[0] > 1 && (!_piped[8] || !_piped[7])) 64 | pipe(_out_fd); 65 | pid = fork(); 66 | if (!pid) 67 | exec_builtin_and_exit(_cmd_, env, _out_fd, _piped); 68 | if (_piped[8] && _piped[7]) 69 | { 70 | close(_out_fd[1]); 71 | _piped[7] = 0; 72 | } 73 | if (!_piped[6] && !_piped[7]) 74 | _piped[8] = 0; 75 | if (_piped[0] > 1 && (!_piped[8] || !_piped[7])) 76 | { 77 | close(_out_fd[1]); 78 | _fd[0] = _out_fd[0]; 79 | } 80 | return (1); 81 | } 82 | 83 | int is_string_numeric(char *s_1) 84 | { 85 | int a; 86 | 87 | a = 0; 88 | while (s_1[a]) 89 | { 90 | if (!ft_isdigit(s_1[a])) 91 | return (0); 92 | a++; 93 | } 94 | return (1); 95 | } 96 | 97 | int manage_builtin_execution(char **_cmd_, int *_fd, t_env *env, int *_piped) 98 | { 99 | int status; 100 | 101 | status = 0; 102 | _piped[10] += 1; 103 | if (_piped[0]) 104 | { 105 | if (!_piped[8]) 106 | status = simple_child_for_builtins(_cmd_, _fd, env, _piped); 107 | else 108 | status = execute_child_with_redirections(_cmd_, _fd, env, _piped); 109 | free_string_array(_cmd_); 110 | } 111 | else 112 | status = manage_single_builtin_execution(_cmd_, _fd, env, _piped); 113 | return (status); 114 | } 115 | -------------------------------------------------------------------------------- /minishell/src/04_execution/builtin_command_execution2.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* builtin_command_execution2.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/29 12:53:43 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:37:38 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int execute_builtin_with_piping(char **_cmd_, int *_fd, t_env *env, int *_piped) 16 | { 17 | int status; 18 | int _out_fd[2]; 19 | 20 | _out_fd[1] = 1; 21 | if (_piped[0] > 1) 22 | pipe(_out_fd); 23 | status = execute_builtin_command_in_child(_cmd_, env, _out_fd, _piped); 24 | if (_piped[0] > 1) 25 | { 26 | close(_out_fd[1]); 27 | _fd[0] = _out_fd[0]; 28 | } 29 | return (status); 30 | } 31 | 32 | int execute_builtin_with_simple_piping( 33 | char **_cmd_, int *_fd, t_env *env, int *_piped) 34 | { 35 | int status; 36 | int _out_fd[2]; 37 | 38 | _out_fd[1] = 1; 39 | if (_piped[8] && _piped[7]) 40 | _out_fd[1] = _piped[2]; 41 | if (_piped[0] > 1 && (!_piped[8] || !_piped[7])) 42 | pipe(_out_fd); 43 | status = execute_builtin_command_in_child(_cmd_, env, _out_fd, _piped); 44 | if (_piped[8] && _piped[7]) 45 | { 46 | close(_out_fd[1]); 47 | _piped[7] = 0; 48 | } 49 | if (!_piped[6] && !_piped[7]) 50 | _piped[8] = 0; 51 | if (_piped[0] > 1 && (!_piped[8] || !_piped[7])) 52 | { 53 | close(_out_fd[1]); 54 | _fd[0] = _out_fd[0]; 55 | } 56 | return (status); 57 | } 58 | 59 | int manage_single_builtin_execution( 60 | char **_cmd_, int *_fd, t_env *env, int *_piped) 61 | { 62 | int status; 63 | int ex_status; 64 | 65 | status = 0; 66 | if (str_cmp(_cmd_[0], "exit", NULL)) 67 | { 68 | ex_status = 0; 69 | if (_cmd_[1] && _cmd_[2]) 70 | return (1); 71 | if (_cmd_[1] && !is_string_numeric(_cmd_[1])) 72 | ex_status = 255; 73 | else if (_cmd_[1]) 74 | ex_status = string_to_int(_cmd_[1]); 75 | free_string_array(_cmd_); 76 | ft_putendl_fd("EXIT", 1); 77 | cleanup_and_exit_shell(env, ex_status); 78 | } 79 | else if (!_piped[8]) 80 | status = execute_builtin_with_piping(_cmd_, _fd, env, _piped); 81 | else 82 | status = execute_builtin_with_simple_piping(_cmd_, _fd, env, _piped); 83 | return (status); 84 | } 85 | -------------------------------------------------------------------------------- /minishell/src/04_execution/command_execution_adv.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* command_execution_adv.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:01:18 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 10:20:35 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int execute_command_basic(char **_cmd_, int *_fd, char **env, int *_piped) 16 | { 17 | pid_t pid; 18 | int fd_[2]; 19 | 20 | pipe(fd_); 21 | pid = fork(); 22 | signal(SIGINT, child_ctrl_c); 23 | signal(SIGQUIT, child_ctrl_c); 24 | if (!pid) 25 | { 26 | if (_piped[0] && _piped[0] <= _piped[5]) 27 | dup2(_fd[0], 0); 28 | if (_piped[0] > 1) 29 | dup2(fd_[1], 1); 30 | else 31 | close(_fd[0]); 32 | close_pipe_ends(fd_[0], fd_[1]); 33 | execve(_cmd_[0], _cmd_, env); 34 | (ft_putendl_fd(strerror(errno), 2), exit(127)); 35 | } 36 | close_pipe_ends(fd_[1], _fd[0]); 37 | if (_piped[0] > 1) 38 | _fd[0] = fd_[0]; 39 | else 40 | close(fd_[0]); 41 | return (1); 42 | } 43 | 44 | int execute_command_with_redirection( 45 | char **_cmd_, int *_fd, char **env, int *_piped) 46 | { 47 | pid_t pid; 48 | int fd_[2]; 49 | 50 | pipe(fd_); 51 | pid = fork(); 52 | signal(SIGINT, child_ctrl_c); 53 | signal(SIGQUIT, child_ctrl_c); 54 | if (!pid) 55 | { 56 | child_fds_managment(_piped, _fd, fd_); 57 | execve(_cmd_[0], _cmd_, env); 58 | ft_putendl_fd(strerror(errno), 2); 59 | exit(127); 60 | } 61 | parent_fds_managment(_piped, _fd, fd_); 62 | free_string_array(_cmd_); 63 | return (1); 64 | } 65 | 66 | int prepare_and_execute_command( 67 | char **_cmd_, int *_fd, int *_piped, t_env *env) 68 | { 69 | char **cmd_args; 70 | char **f_args; 71 | int status; 72 | 73 | f_args = prepare_cmd_arguments(_cmd_[0], env->original_env, 0); 74 | cmd_args = merge_command_args(f_args, _cmd_); 75 | if (check_if_command_is_builtin(cmd_args[0])) 76 | status = manage_builtin_execution(cmd_args, _fd, env, _piped); 77 | else 78 | { 79 | _piped[10] += 1; 80 | if (!_piped[8]) 81 | { 82 | status = execute_command_basic( 83 | cmd_args, _fd, env->original_env, _piped); 84 | free_string_array(cmd_args); 85 | } 86 | else 87 | status = execute_command_with_redirection( 88 | cmd_args, _fd, env->original_env, _piped); 89 | } 90 | if (_piped[0] > 1) 91 | _piped[0] -= 1; 92 | return (status); 93 | } 94 | 95 | int wait_for_children(int status, int *_piped) 96 | { 97 | if (status != 2 && status != 127 98 | && status != 126 && _piped[10] 99 | && _piped[11]) 100 | { 101 | while (_piped[10]) 102 | { 103 | wait(&status); 104 | _piped[10] -= 1; 105 | } 106 | signal(SIGINT, handle_ctrl_c); 107 | signal(SIGQUIT, SIG_IGN); 108 | if (!g_var_thing) 109 | return (WEXITSTATUS(status)); 110 | else 111 | return (g_var_thing); 112 | } 113 | return (status); 114 | } 115 | -------------------------------------------------------------------------------- /minishell/src/04_execution/command_execution_control.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* command_execution_control.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:11:08 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 14:13:13 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void initialize_or_reset_pipe_state(int *_piped, int f) 16 | { 17 | int a; 18 | 19 | a = 0; 20 | _piped[0] = _piped[5]; 21 | if (f) 22 | while (a < 12) 23 | _piped[a++] = 0; 24 | else if (_piped[5]) 25 | _piped[0] += 1; 26 | _piped[11] = 1; 27 | } 28 | 29 | int switch_fds_identifier( 30 | int *_piped, int index, int index_2, int con) 31 | { 32 | if (con) 33 | { 34 | if (_piped[index]) 35 | close(_piped[index_2]); 36 | _piped[index] = 1; 37 | } 38 | else 39 | { 40 | ft_putendl_fd("err: file not found", 2); 41 | _piped[6] = 0; 42 | } 43 | return (1); 44 | } 45 | 46 | int open_file_for_redirection( 47 | t_ast_node *head, int *_piped, t_env *env, int status) 48 | { 49 | int mode; 50 | 51 | if (head->file_type == READ_FILE) 52 | { 53 | switch_fds_identifier(_piped, 6, 1, 1); 54 | _piped[1] = open(head->args[0], O_RDONLY); 55 | if (_piped[1] < 0) 56 | status = switch_fds_identifier(_piped, 0, 0, 0); 57 | } 58 | else if (head->file_type == READ_FROM_APPEND) 59 | { 60 | switch_fds_identifier(_piped, 6, 1, 1); 61 | status = exec_here_doc(head->args[0], _piped, env); 62 | signal(SIGINT, handle_ctrl_c); 63 | } 64 | else 65 | { 66 | switch_fds_identifier(_piped, 7, 2, 1); 67 | mode = O_TRUNC; 68 | if (head->file_type == WRITE_FILE_APPEND) 69 | mode = O_APPEND; 70 | _piped[2] = open(head->args[0], O_WRONLY | O_CREAT | mode, 0666); 71 | } 72 | return (status); 73 | } 74 | 75 | int check_if_command_is_builtin(char *_cmd) 76 | { 77 | char *tmp_cmd; 78 | int status; 79 | 80 | status = 0; 81 | tmp_cmd = malloc(sizeof_str(_cmd, ' ') + 1); 82 | if (!tmp_cmd) 83 | return (0); 84 | s_strcopy(tmp_cmd, _cmd, 0, sizeof_str(_cmd, ' ')); 85 | if (str_cmp(tmp_cmd, "echo", "cd") 86 | || str_cmp(tmp_cmd, "pwd", "export") 87 | || str_cmp(tmp_cmd, "unset", "env") 88 | || str_cmp(tmp_cmd, "exit", NULL)) 89 | status = 1; 90 | free(tmp_cmd); 91 | return (status); 92 | } 93 | 94 | int execute_builtin_command_in_child( 95 | char **_cmd_, t_env *env, int *_out_fd, int *_piped) 96 | { 97 | int status; 98 | 99 | status = 0; 100 | (void)_piped; 101 | if (str_cmp(_cmd_[0], "echo", NULL)) 102 | status = echo_cmd(_cmd_, _out_fd); 103 | else if (str_cmp(_cmd_[0], "pwd", "env")) 104 | status = env_or_pwd_cmd(_cmd_[0], env, 0, _out_fd); 105 | else if (str_cmp(_cmd_[0], "export", "unset")) 106 | _cmd_ = unset_or_export_cmd(_cmd_, env, _out_fd, &status); 107 | else if (str_cmp(_cmd_[0], "cd", NULL)) 108 | status = cd_cmd(_cmd_, env, _out_fd); 109 | else if (str_cmp(_cmd_[0], "exit", NULL)) 110 | __exit(_cmd_); 111 | free_string_array(_cmd_); 112 | return (status); 113 | } 114 | -------------------------------------------------------------------------------- /minishell/src/04_execution/command_input_preprocessing.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* command_input_preprocessing.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:12:09 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 16:05:44 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | char **merge_command_args(char **f_args, char **_cmd_) 16 | { 17 | int a; 18 | char **new_args; 19 | 20 | if (!f_args) 21 | return (NULL); 22 | a = 1; 23 | while (_cmd_[0] && _cmd_[a]) 24 | a++; 25 | new_args = malloc((a + 1) * sizeof(char *)); 26 | if (!new_args) 27 | return (NULL); 28 | a = 0; 29 | if (f_args[a]) 30 | new_args[a] = strcopy(f_args[a]); 31 | else 32 | new_args[a] = strcopy(""); 33 | if (_cmd_ && _cmd_[0]) 34 | { 35 | while (_cmd_[++a]) 36 | new_args[a] = strcopy(_cmd_[a]); 37 | } 38 | new_args[a] = 0; 39 | free_string_array(f_args); 40 | return (new_args); 41 | } 42 | -------------------------------------------------------------------------------- /minishell/src/04_execution/executor.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* executor.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:02:22 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 16:38:06 by zelhajou ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | ///// the rules 16 | /// 17 | /// _piped[0]: executed pipes index 18 | /// 19 | /// _piped[3]: input files_count 20 | /// _piped[4]: output files count 21 | /// _piped[5]: pipes count 22 | /// 23 | /// _piped[1]: current input file fd 24 | /// _piped[2]: current output file fd 25 | /// 26 | /// _piped[6]: if there is an in file 27 | /// _piped[7]: if there is an out file 28 | /// _piped[8]: if its a redirection/piped execute 29 | /// 30 | /// _piped[9]: heredoc status 31 | /// _piped[10]: children count 32 | /// _piped[11]: second heredoc status 33 | ///// 34 | int g_var_thing; 35 | 36 | int handle_piped_command_execution( 37 | t_ast_node *head, int *_piped, t_env *env, int *_fd) 38 | { 39 | int status; 40 | 41 | if (head->file_type == EXECUTE_FILE) 42 | { 43 | _piped[8] = 0; 44 | status = prepare_and_execute_command(head->args, _fd, _piped, env); 45 | } 46 | if (head->type == TOKEN_REDIR_IN 47 | || head->type == TOKEN_REDIR_OUT 48 | || head->type == TOKEN_REDIR_APPEND 49 | || head->type == TOKEN_REDIR_HEREDOC) 50 | return (handle_command_redirection(head, _piped, env, _fd)); 51 | if (head->left) 52 | status = handle_piped_command_execution(head->left, _piped, env, _fd); 53 | if (head->right) 54 | status = handle_piped_command_execution(head->right, _piped, env, _fd); 55 | return (status); 56 | } 57 | 58 | int handle_command_redirection( 59 | t_ast_node *head, int *_piped, t_env *env, int *_fd) 60 | { 61 | int status; 62 | 63 | _piped[11] = 1; 64 | if (head->right) 65 | { 66 | status = open_file_for_redirection(head->right, _piped, env, 0); 67 | if ((status || !head->left) && _piped[0] > 1) 68 | _piped[0] -= 1; 69 | } 70 | if (head->left && head->left->file_type == EXECUTE_FILE 71 | && _piped[11] && !status) 72 | { 73 | _piped[8] = 1; 74 | status = prepare_and_execute_command( 75 | head->left->args, _fd, _piped, env); 76 | } 77 | if (head->left && head->left->type == TOKEN_PIPE 78 | && _piped[11]) 79 | status = handle_piped_command_execution(head->left, _piped, env, _fd); 80 | if (head->left && (head->left->type == TOKEN_REDIR_IN 81 | || head->left->type == TOKEN_REDIR_OUT 82 | || head->left->type == TOKEN_REDIR_APPEND 83 | || head->left->type == TOKEN_REDIR_HEREDOC)) 84 | status = handle_command_redirection(head->left, _piped, env, _fd); 85 | return (status); 86 | } 87 | 88 | int execute_ast_node(t_ast_node *head, int *_piped, t_env *env) 89 | { 90 | int _fd[2]; 91 | int status; 92 | 93 | _fd[0] = -1; 94 | _fd[1] = -1; 95 | if (head->file_type == FILE_READY) 96 | { 97 | if (head->type == TOKEN_PIPE) 98 | status = handle_piped_command_execution(head, _piped, env, _fd); 99 | if (head->type == TOKEN_REDIR_IN 100 | || head->type == TOKEN_REDIR_OUT 101 | || head->type == TOKEN_REDIR_APPEND 102 | || head->type == TOKEN_REDIR_HEREDOC) 103 | status = handle_command_redirection(head, _piped, env, _fd); 104 | } 105 | if (head->file_type == EXECUTE_FILE) 106 | status = prepare_and_execute_command(head->args, _fd, _piped, env); 107 | status = wait_for_children(status, _piped); 108 | if (_piped[6]) 109 | close(_piped[1]); 110 | if (_piped[7]) 111 | close(_piped[2]); 112 | if (_fd[0] != -1 || _fd[1] != -1) 113 | (close(_fd[0]), close(_fd[1])); 114 | return (g_var_thing = 0, status); 115 | } 116 | 117 | void command_execution_manager(t_ast_node *head, t_env *env, int *status) 118 | { 119 | int _piped[13]; 120 | int _status; 121 | 122 | initialize_or_reset_pipe_state(_piped, 1); 123 | count_redirections_and_pipes(head, _piped); 124 | initialize_or_reset_pipe_state(_piped, 0); 125 | adjust_ast_nodes_for_execution(head); 126 | expand_variables_in_ast(head, env); 127 | _status = verify_command_file_permissions(head, env->original_env); 128 | if (!_status) 129 | *status = execute_ast_node(head, _piped, env); 130 | } 131 | -------------------------------------------------------------------------------- /minishell/src/04_execution/heredoc_handling.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* heredoc_handling.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:16:55 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:40:30 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int str_compare(char *s_1, char *s_2, int max) 16 | { 17 | int a; 18 | 19 | a = 0; 20 | while (a < max && *s_1 && *s_2 21 | && s_1[a] == s_2[a]) 22 | a++; 23 | if (sizeof_str(s_1, '\0') == a 24 | && a == max) 25 | return (1); 26 | return (0); 27 | } 28 | 29 | void quite_heredoc(int a) 30 | { 31 | (void)a; 32 | write(1, "\n", 1); 33 | exit(0); 34 | } 35 | 36 | int is_there_any_quotes(char *s) 37 | { 38 | int a; 39 | 40 | a = 0; 41 | while (s && s[a]) 42 | { 43 | if (s[a] == 34 || s[a] == 39) 44 | return (0); 45 | a++; 46 | } 47 | return (1); 48 | } 49 | 50 | void read_and_write( 51 | int std_out, char *limiter, t_env *env, int is_expandable) 52 | { 53 | char *buf; 54 | int f_arr[3]; 55 | 56 | limiter = remove_quotes_from_str(limiter, 0, 0, 0); 57 | while (1) 58 | { 59 | buf = readline(">> "); 60 | if (!buf || str_compare(limiter, buf, sizeof_str(buf, '\n'))) 61 | { 62 | free(buf); 63 | break ; 64 | } 65 | if (is_expandable) 66 | { 67 | buf[sizeof_str(buf, '\n')] = '\0'; 68 | ft_memset(f_arr, 0, 3 * sizeof(int)); 69 | buf = recursively_expand_variables(buf, env, 0, f_arr); 70 | ft_memset(f_arr, 0, 3 * sizeof(int)); 71 | buf = recursively_expand_variables(buf, env, 1, f_arr); 72 | } 73 | write(std_out, buf, sizeof_str(buf, '\0')); 74 | write(std_out, "\n", 1); 75 | free(buf); 76 | } 77 | free(limiter); 78 | } 79 | 80 | int exec_here_doc(char *limiter, int *_piped, t_env *env) 81 | { 82 | int _out_fd_[2]; 83 | pid_t pid; 84 | int status; 85 | 86 | pipe(_out_fd_); 87 | pid = fork(); 88 | signal(SIGINT, SIG_IGN); 89 | if (!pid) 90 | { 91 | signal(SIGINT, quite_heredoc); 92 | close(_out_fd_[0]); 93 | read_and_write(_out_fd_[1], limiter, env, 94 | is_there_any_quotes(limiter)); 95 | exit(1); 96 | } 97 | waitpid(pid, &status, 0); 98 | close(_out_fd_[1]); 99 | _piped[1] = _out_fd_[0]; 100 | _piped[9] = (WEXITSTATUS(status)) - 1; 101 | if (_piped[9] < 0) 102 | _piped[9] += 2; 103 | _piped[11] = status; 104 | return (_piped[9]); 105 | } 106 | -------------------------------------------------------------------------------- /minishell/src/04_execution/initialization/command_execution_init.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* command_execution_init.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 09:56:04 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 13:59:33 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void sus_dir_check(char *path_, char *file, int *status) 16 | { 17 | struct stat s; 18 | 19 | if (file && str_cmp(file, ".", NULL)) 20 | *status = 2; 21 | else if (str_cmp(file, "..", NULL) 22 | || str_cmp(file, ",", "")) 23 | { 24 | *status = 1; 25 | errno = 2; 26 | } 27 | else if (!stat(path_, &s) 28 | && s.st_mode & S_IFDIR) 29 | { 30 | *status = 2; 31 | ft_putstr_fd(" err: this \'", 2); 32 | ft_putstr_fd(path_, 2); 33 | ft_putendl_fd("\' Is a directory", 2); 34 | errno = 13; 35 | } 36 | } 37 | 38 | int specify_what_error_stuff(char *file, int _status) 39 | { 40 | if (_status == 1) 41 | { 42 | _status = get_shell_exit_status(errno); 43 | ft_putstr_fd(" err: \'", 2); 44 | ft_putstr_fd(file, 2); 45 | ft_putstr_fd("\' ", 2); 46 | ft_putendl_fd(strerror(errno), 2); 47 | return (_status); 48 | } 49 | else if (_status) 50 | { 51 | ft_putstr_fd(" minishell(\'", 2); 52 | ft_putstr_fd(file, 2); 53 | ft_putendl_fd("\'): go play somewhere elsz", 2); 54 | } 55 | return (_status); 56 | } 57 | 58 | int verify_command_file_permissions(t_ast_node *head, char **env) 59 | { 60 | int status; 61 | char *path_; 62 | 63 | status = 0; 64 | if (head->args 65 | && !check_if_command_is_builtin(head->args[0]) 66 | && head->file_type == READ_FILE) 67 | { 68 | path_ = fetch_file_path(head->args[0], env, "PWD", R_OK); 69 | if (!path_) 70 | status = 0; 71 | else 72 | { 73 | sus_dir_check(path_, head->args[0], &status); 74 | free(path_); 75 | } 76 | status = specify_what_error_stuff(head->args[0], status); 77 | } 78 | if (!status && head->left) 79 | status = verify_command_file_permissions(head->left, env); 80 | if (!status && head->right) 81 | status = verify_command_file_permissions(head->right, env); 82 | return (status); 83 | } 84 | 85 | void adjust_ast_nodes_for_execution(t_ast_node *head) 86 | { 87 | if (head->type != TOKEN_WORD) 88 | { 89 | head->file_type = FILE_READY; 90 | if (head->type == TOKEN_REDIR_OUT && head->right) 91 | head->right->file_type = WRITE_FILE; 92 | if (head->type == TOKEN_REDIR_APPEND && head->right) 93 | head->right->file_type = WRITE_FILE_APPEND; 94 | if (head->type == TOKEN_REDIR_IN && head->right) 95 | head->right->file_type = READ_FILE; 96 | if (head->type == TOKEN_REDIR_HEREDOC && head->right) 97 | head->right->file_type = READ_FROM_APPEND; 98 | if (head->type == TOKEN_PIPE) 99 | { 100 | if (head->right) 101 | head->right->file_type = EXECUTE_FILE; 102 | if (head->left) 103 | head->left->file_type = EXECUTE_FILE; 104 | } 105 | } 106 | if (!head->file_type) 107 | head->file_type = EXECUTE_FILE; 108 | if (head->left) 109 | adjust_ast_nodes_for_execution(head->left); 110 | if (head->right) 111 | adjust_ast_nodes_for_execution(head->right); 112 | } 113 | 114 | void count_redirections_and_pipes(t_ast_node *head, int *_piped) 115 | { 116 | head->file_type = 0; 117 | if (head->type == TOKEN_REDIR_OUT 118 | || head->type == TOKEN_REDIR_APPEND) 119 | _piped[4] += 1; 120 | else if (head->type == TOKEN_REDIR_IN 121 | || head->type == TOKEN_REDIR_HEREDOC) 122 | _piped[3] += 1; 123 | else if (head->type == TOKEN_PIPE) 124 | _piped[5] += 1; 125 | if (head->left) 126 | count_redirections_and_pipes(head->left, _piped); 127 | if (head->right) 128 | count_redirections_and_pipes(head->right, _piped); 129 | } 130 | -------------------------------------------------------------------------------- /minishell/src/04_execution/initialization/environment_init.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* environment_init.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 09:55:35 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:44:12 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | char **duplicate_environment_variables(char **env) 16 | { 17 | int a; 18 | int b; 19 | char **new_old; 20 | 21 | a = 0; 22 | b = 0; 23 | while (env[a]) 24 | a++; 25 | new_old = malloc((a + 1) * sizeof(char **)); 26 | if (!new_old) 27 | return (NULL); 28 | while (b < a) 29 | { 30 | new_old[b] = strcopy(env[b]); 31 | b++; 32 | } 33 | new_old[b] = 0; 34 | return (new_old); 35 | } 36 | 37 | int initialize_shell_environment_structure( 38 | t_env *env, char **original_env, int a) 39 | { 40 | int b; 41 | int c; 42 | 43 | env->original_env = duplicate_environment_variables(original_env); 44 | while (original_env[a]) 45 | a++; 46 | env->parsed_env = malloc((a + 1) * sizeof(char ***)); 47 | if (!env->parsed_env) 48 | return (0); 49 | b = -1; 50 | while (++b < a) 51 | { 52 | c = sizeof_str(original_env[b], '='); 53 | env->parsed_env[b] = malloc(2 * sizeof(char **)); 54 | env->parsed_env[b][0] = malloc(c * sizeof(char *)); 55 | env->parsed_env[b][1] = malloc( 56 | (sizeof_str(original_env[b], '\0') - c) * sizeof(char *)); 57 | if (!env->parsed_env[b] || !env->parsed_env[b][0] 58 | || !env->parsed_env[b][1]) 59 | return (0); 60 | s_strcopy(env->parsed_env[b][0], original_env[b], 0, c); 61 | s_strcopy(env->parsed_env[b][1], original_env[b], 62 | c + 1, sizeof_str(original_env[b], '\0')); 63 | } 64 | return (env->parsed_env[b] = 0, 1); 65 | } 66 | 67 | void initialize_default_variables(t_env *env, int a) 68 | { 69 | char *new_pwd; 70 | 71 | a = find_env_var_index(env, "SHELL"); 72 | if (a >= 0) 73 | remove_env_entry(env, a); 74 | replace_env_var("SHELL=minishell", env); 75 | replace_env_var("?=0", env); 76 | a = find_env_var_index(env, "PWD"); 77 | new_pwd = get_current_working_directory(100, 5, 2); 78 | if (new_pwd) 79 | { 80 | if (a >= 0) 81 | remove_env_entry(env, a); 82 | set_new_pwd_in_env(new_pwd, env, a); 83 | free(new_pwd); 84 | } 85 | } 86 | 87 | int initialize_shell_with_environment(t_env *env, char **original_env) 88 | { 89 | int __index; 90 | int status; 91 | int a; 92 | 93 | if (!env) 94 | return (0); 95 | status = initialize_shell_environment_structure(env, original_env, 0); 96 | a = find_env_var_index(env, "SHLVL"); 97 | __index = 0; 98 | if (a >= 0) 99 | __index = string_to_int(env->parsed_env[a][1]); 100 | update_env_status(env, __index + 1, "SHLVL="); 101 | initialize_default_variables(env, 0); 102 | return (status); 103 | } 104 | -------------------------------------------------------------------------------- /minishell/src/04_execution/path_utilities.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* path_utilities.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:03:19 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:42:25 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | char *create_subpath_from_var(char *env_var, char *file, int *indx_s) 16 | { 17 | char *tmp_path; 18 | int a; 19 | int b; 20 | int file_size; 21 | 22 | increment_path_index(env_var, indx_s, &a); 23 | file_size = sizeof_str(file, ' '); 24 | tmp_path = malloc((indx_s[1] - a) + file_size + 2); 25 | if (!tmp_path) 26 | return (NULL); 27 | b = 0; 28 | while (b < ((indx_s[1] - a) + file_size + 1)) 29 | { 30 | if (indx_s[3] && (b < indx_s[1] - a)) 31 | tmp_path[b] = env_var[a + b]; 32 | else if (indx_s[3] 33 | && env_var[indx_s[1] - 1] != '/' 34 | && (b == indx_s[1] - a)) 35 | tmp_path[b] = '/'; 36 | else 37 | tmp_path[b] = file[b - (indx_s[1] - a) - indx_s[3]]; 38 | b++; 39 | } 40 | tmp_path[b] = '\0'; 41 | return (tmp_path); 42 | } 43 | 44 | char *verify_path_without_env(char *file, int mode) 45 | { 46 | char *tmp_path; 47 | int b; 48 | 49 | b = sizeof_str(file, ' '); 50 | tmp_path = malloc(b + 1); 51 | if (!tmp_path) 52 | return (NULL); 53 | s_strcopy(tmp_path, file, 0, b); 54 | if (is_path_accessible(tmp_path, mode)) 55 | return (tmp_path); 56 | free(tmp_path); 57 | return (NULL); 58 | } 59 | 60 | char *fetch_file_path(char *file, char **envp, char *env_var, int mode) 61 | { 62 | char *tmp_path; 63 | int indx_s[4]; 64 | 65 | indx_s[3] = 0; 66 | indx_s[1] = sizeof_str(env_var, '\0'); 67 | indx_s[0] = find_substr_index(envp, env_var, indx_s[1]); 68 | if (indx_s[0] < 0 69 | || (file[0] && file[1] && file[0] == '.' && file[1] == '/')) 70 | return (verify_path_without_env(file, mode)); 71 | indx_s[2] = sizeof_str(envp[indx_s[0]], '\0'); 72 | if (sizeof_str(file, ' ') != sizeof_str(file, '\0') 73 | && !is_path_accessible(file, mode)) 74 | return (NULL); 75 | while (envp[indx_s[0]][indx_s[1]]) 76 | { 77 | tmp_path = create_subpath_from_var(envp[indx_s[0]], file, indx_s); 78 | if (!tmp_path) 79 | return (NULL); 80 | if (is_path_accessible(tmp_path, mode)) 81 | return (tmp_path); 82 | free(tmp_path); 83 | if (!indx_s[3]) 84 | indx_s[3] = 1; 85 | } 86 | return (NULL); 87 | } 88 | 89 | char *find_next_substring(char *str, char del, int *index) 90 | { 91 | char *sub; 92 | int size; 93 | int a; 94 | 95 | while (str[index[0]] && str[index[0]] == del) 96 | index[0] += 1; 97 | size = sizeof_str(str + index[0], del); 98 | sub = malloc(size + 1); 99 | if (!sub) 100 | return (NULL); 101 | a = 0; 102 | while (str[index[0]] 103 | && str[index[0]] != del) 104 | { 105 | if (str[index[0]] != 34 && str[index[0]] != 39) 106 | sub[a++] = str[index[0]]; 107 | index[0] += 1; 108 | } 109 | sub[a] = '\0'; 110 | index[0] += 1; 111 | return (sub); 112 | } 113 | 114 | char **prepare_cmd_arguments(char *cmd, char **envp, int c) 115 | { 116 | char **cmd_arr; 117 | char *cmd_holder; 118 | int i[3]; 119 | 120 | i[1] = count_substrings(cmd, ' '); 121 | cmd_arr = malloc((i[1] + 1) * sizeof(char *)); 122 | i[0] = 0; 123 | while (c < i[1]) 124 | { 125 | cmd_holder = find_next_substring(cmd, '\0', i); 126 | if (!c && !check_if_command_is_builtin(cmd_holder)) 127 | { 128 | cmd_arr[c] = fetch_file_path(cmd_holder, envp, "PATH", X_OK); 129 | if (!cmd_arr[c]) 130 | cmd_arr[c] = ft_strdup(cmd_holder); 131 | free(cmd_holder); 132 | } 133 | else 134 | cmd_arr[c] = cmd_holder; 135 | if (!cmd_arr[c]) 136 | return (NULL); 137 | c += 1; 138 | } 139 | cmd_arr[c] = NULL; 140 | return (cmd_arr); 141 | } 142 | -------------------------------------------------------------------------------- /minishell/src/04_execution/path_utilities2.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* path_utilities2.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:03:32 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:42:59 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int find_substr_index(char **haystack, char *needle, int n_length) 16 | { 17 | int a; 18 | int b; 19 | 20 | a = 0; 21 | while (haystack[a] != 0) 22 | { 23 | if (haystack[a][0] == needle[0]) 24 | { 25 | b = 0; 26 | while (haystack[a][b] 27 | && haystack[a][b] == needle[b]) 28 | { 29 | if (b == n_length - 1) 30 | return (a); 31 | b++; 32 | } 33 | } 34 | a++; 35 | } 36 | return (-1); 37 | } 38 | 39 | int is_path_accessible(char *path, int mode) 40 | { 41 | if (access(path, mode) < 0) 42 | return (0); 43 | return (1); 44 | } 45 | 46 | void increment_path_index(char *env_var, int *indx_s, int *a) 47 | { 48 | if (indx_s[3]) 49 | { 50 | indx_s[1] += 1; 51 | *a = indx_s[1]; 52 | while (env_var[indx_s[1]] != '\0' 53 | && env_var[indx_s[1]] != ':') 54 | indx_s[1] += 1; 55 | } 56 | else 57 | *a = indx_s[1]; 58 | } 59 | 60 | int count_substrings(char *str, char del) 61 | { 62 | int a; 63 | int b; 64 | int res; 65 | 66 | a = 0; 67 | b = 1; 68 | res = 0; 69 | while (str && str[a]) 70 | { 71 | if (str[a] != del) 72 | { 73 | if (b) 74 | res += 1; 75 | b = 0; 76 | } 77 | else 78 | b = 1; 79 | a += 1; 80 | } 81 | return (res); 82 | } 83 | -------------------------------------------------------------------------------- /minishell/src/04_execution/process_pipeline_management.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* process_pipeline_management.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:02:37 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:43:24 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void child_fds_managment(int *_piped, int *_fd, int *fd_) 16 | { 17 | if (_piped[8] && _piped[6]) 18 | { 19 | dup2(_piped[1], 0); 20 | close(_piped[1]); 21 | } 22 | if (_piped[8] && _piped[7]) 23 | { 24 | dup2(_piped[2], 1); 25 | close(_piped[2]); 26 | } 27 | if (_piped[0] && _piped[0] <= _piped[5] 28 | && (!_piped[8] || !_piped[6])) 29 | dup2(_fd[0], 0); 30 | if (_piped[0] > 1 && (!_piped[8] || !_piped[7])) 31 | dup2(fd_[1], 1); 32 | else 33 | close(fd_[0]); 34 | close(fd_[0]); 35 | close(fd_[1]); 36 | } 37 | 38 | void parent_fds_managment(int *_piped, int *_fd, int *fd_) 39 | { 40 | if (_piped[8] && _piped[6]) 41 | { 42 | close(_piped[1]); 43 | _piped[6] = 0; 44 | } 45 | if (_piped[8] && _piped[7]) 46 | { 47 | close(_piped[2]); 48 | _piped[7] = 0; 49 | } 50 | if (!_piped[7] && !_piped[6]) 51 | _piped[8] = 0; 52 | close(fd_[1]); 53 | close(_fd[0]); 54 | if (_piped[0] > 1) 55 | _fd[0] = fd_[0]; 56 | else 57 | close(fd_[0]); 58 | } 59 | -------------------------------------------------------------------------------- /minishell/src/05_builtin/builtin_commands.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* builtin_commands.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:00:08 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:46:01 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int echo_cmd(char **_cmd, int *_out_fd) 16 | { 17 | int a; 18 | int op_n; 19 | 20 | op_n = 0; 21 | if (_cmd[0] && _cmd[1] && is_valid_echo_param(_cmd[1])) 22 | op_n = 1; 23 | a = op_n + 1; 24 | while (op_n && _cmd[a] && is_valid_echo_param(_cmd[a])) 25 | a++; 26 | if ((_cmd[0] && _cmd[a]) || sizeof_str(_cmd[a], '\0')) 27 | { 28 | while (1) 29 | { 30 | ft_putstr_fd(_cmd[a], _out_fd[1]); 31 | a++; 32 | if (_cmd[a]) 33 | write(_out_fd[1], " ", 1); 34 | else 35 | break ; 36 | } 37 | } 38 | if (!op_n) 39 | write(_out_fd[1], "\n", 1); 40 | return (0); 41 | } 42 | 43 | int env_or_pwd_cmd(char *_cmd, t_env *env, int con, int *_out_fd) 44 | { 45 | int a; 46 | char *abs_pwd; 47 | 48 | a = -1; 49 | if (str_cmp(_cmd, "env", NULL)) 50 | { 51 | if (con) 52 | print_export_declaration_to_fd(env, _out_fd); 53 | else 54 | { 55 | while (env->parsed_env[++a]) 56 | print_env_var_to_fd( 57 | env->parsed_env[a][0], env->parsed_env[a][1], _out_fd[1]); 58 | } 59 | return (0); 60 | } 61 | abs_pwd = get_current_working_directory(100, 5, _out_fd[1]); 62 | if (abs_pwd) 63 | { 64 | ft_putendl_fd(abs_pwd, _out_fd[1]); 65 | return (free(abs_pwd), 0); 66 | } 67 | return (256); 68 | } 69 | 70 | char **export_cmd(char **_cmd, t_env *env, int *_out_fd, int **s) 71 | { 72 | int a; 73 | int b; 74 | 75 | a = 1; 76 | while (_cmd[a]) 77 | { 78 | b = export_statment_check(_cmd[a]); 79 | if (b > 0) 80 | { 81 | if (b >= 1 && _cmd[a][b] == '+') 82 | append_env_var(_cmd[a], env); 83 | else 84 | replace_env_var(_cmd[a], env); 85 | } 86 | else 87 | { 88 | ft_putstr_fd(" err: export(\'", _out_fd[1]); 89 | ft_putstr_fd(_cmd[a], _out_fd[1]); 90 | ft_putendl_fd("\') : Not a valid thing", 91 | _out_fd[1]); 92 | **s = 256; 93 | } 94 | a++; 95 | } 96 | return (_cmd); 97 | } 98 | 99 | char **unset_or_export_cmd(char **_cmd, t_env *env, int *_out_fd, int *s) 100 | { 101 | int a; 102 | int c; 103 | 104 | a = 1; 105 | *s = 0; 106 | if (_cmd[a] && str_cmp(_cmd[0], "unset", NULL) && env->parsed_env[0]) 107 | { 108 | while (_cmd[a]) 109 | { 110 | c = find_env_var_index(env, _cmd[a]); 111 | if (c >= 0) 112 | remove_env_entry(env, c); 113 | else 114 | *s = 256; 115 | a++; 116 | } 117 | } 118 | else if (str_cmp(_cmd[0], "export", NULL)) 119 | { 120 | if (export_print_or_export(_cmd)) 121 | _cmd = export_cmd(_cmd, env, _out_fd, &s); 122 | else 123 | env_or_pwd_cmd("env", env, 1, _out_fd); 124 | } 125 | return (_cmd); 126 | } 127 | 128 | int cd_cmd(char **_cmd, t_env *env, int *_out_fd) 129 | { 130 | int a; 131 | char *new_path; 132 | 133 | if (_cmd[1] && _cmd[2]) 134 | ft_putendl_fd(" err: cd(): Not a cd thing", _out_fd[1]); 135 | else 136 | { 137 | if (change_current_directory(_cmd[1], env) < 0) 138 | ft_putendl_fd( 139 | " err: cd(): Only EXISTING destinations", _out_fd[1]); 140 | else 141 | { 142 | a = find_env_var_index(env, "PWD"); 143 | if (a >= 0) 144 | remove_env_entry(env, a); 145 | new_path = get_current_working_directory(100, 5, _out_fd[1]); 146 | if (new_path) 147 | { 148 | set_new_pwd_in_env(new_path, env, a); 149 | free(new_path); 150 | } 151 | return (0); 152 | } 153 | } 154 | return (256); 155 | } 156 | -------------------------------------------------------------------------------- /minishell/src/05_builtin/builtin_commands_utils.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* builtin_commands_utils.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 09:59:58 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:46:27 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void set_new_pwd_in_env(char *new_, t_env *env, int c) 16 | { 17 | char **exp_pwd; 18 | int a; 19 | int b; 20 | 21 | a = 0; 22 | b = 4; 23 | (void)c; 24 | exp_pwd = malloc(3 * sizeof(char *)); 25 | if (!exp_pwd) 26 | return ; 27 | exp_pwd[0] = strcopy("export"); 28 | exp_pwd[1] = malloc(sizeof_str(new_, '\0') + 5); 29 | if (!exp_pwd[1]) 30 | return ; 31 | s_strcopy(exp_pwd[1], "PWD=", 0, 4); 32 | while (new_[a]) 33 | exp_pwd[1][b++] = new_[a++]; 34 | exp_pwd[1][b] = '\0'; 35 | exp_pwd[2] = 0; 36 | unset_or_export_cmd(exp_pwd, env, NULL, &a); 37 | free_string_array(exp_pwd); 38 | } 39 | 40 | int change_current_directory(char *path, t_env *env) 41 | { 42 | int status; 43 | int a; 44 | 45 | if (!path || !sizeof_str(path, '\0')) 46 | { 47 | a = find_env_var_index(env, "HOME"); 48 | if (a >= 0) 49 | status = chdir(env->parsed_env[a][1]); 50 | else 51 | status = -1; 52 | } 53 | else 54 | status = chdir(path); 55 | return (status); 56 | } 57 | 58 | char *get_current_working_directory(int size, int tries, int fd) 59 | { 60 | char *buffer; 61 | 62 | buffer = malloc(size); 63 | if (!buffer) 64 | return (NULL); 65 | if (!getcwd(buffer, size)) 66 | { 67 | free(buffer); 68 | if (tries < 10) 69 | return (get_current_working_directory(size + 50, tries + 1, fd)); 70 | else 71 | { 72 | ft_putendl_fd(" err: cd() / pwd(): getcwd(): you are lost", fd); 73 | return (NULL); 74 | } 75 | } 76 | return (buffer); 77 | } 78 | 79 | char ***sort_tha_array(char ***_array, int _si) 80 | { 81 | int a; 82 | int b; 83 | int c; 84 | char **temp_p; 85 | 86 | a = 0; 87 | while (a < _si - 1) 88 | { 89 | b = a + 1; 90 | c = string_weight_compare(_array[a][0], _array[b][0]); 91 | if (c) 92 | { 93 | temp_p = _array[a]; 94 | _array[a] = _array[b]; 95 | _array[b] = temp_p; 96 | } 97 | a++; 98 | } 99 | if (check_array_arrangment(_array, _si)) 100 | return (_array); 101 | return (sort_tha_array(_array, _si)); 102 | } 103 | 104 | void print_export_declaration_to_fd(t_env *env, int *_out_fd) 105 | { 106 | char ***new_array; 107 | int a; 108 | 109 | a = 0; 110 | while (env->parsed_env[a] != 0) 111 | a++; 112 | if (!a) 113 | return ; 114 | new_array = duplicate_env_structure(env, a, 'F', -1); 115 | new_array[a] = 0; 116 | new_array = sort_tha_array(new_array, a); 117 | print_export_vars(new_array, a, _out_fd[1]); 118 | free_environment_variables(new_array); 119 | } 120 | -------------------------------------------------------------------------------- /minishell/src/05_builtin/builtin_commands_utils2.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* builtin_commands_utils2.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/03/04 05:42:06 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:46:43 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void print_env_var_to_fd(char *str_1, char *str_2, int fd) 16 | { 17 | if (!str_cmp(str_1, "?", NULL) 18 | && !str_cmp(str_2, "F1", NULL)) 19 | { 20 | ft_putstr_fd(str_1, fd); 21 | ft_putstr_fd("=", fd); 22 | if (str_2[0]) 23 | ft_putstr_fd(str_2, fd); 24 | write(fd, "\n", 1); 25 | } 26 | } 27 | 28 | void print_export_vars(char ***arr, int a, int fd) 29 | { 30 | while (a--) 31 | { 32 | if (!str_cmp(arr[a][0], "?", NULL)) 33 | { 34 | ft_putstr_fd("declare -x ", fd); 35 | ft_putstr_fd(arr[a][0], fd); 36 | if (!str_cmp(arr[a][1], "F1", NULL)) 37 | { 38 | write(fd, "=", 1); 39 | ft_putchar_fd('"', fd); 40 | if (arr[a][1][0]) 41 | ft_putstr_fd(arr[a][1], fd); 42 | ft_putchar_fd('"', fd); 43 | } 44 | write(fd, "\n", 1); 45 | } 46 | } 47 | } 48 | 49 | int string_weight_compare(char *s_1, char *s_2) 50 | { 51 | int a; 52 | 53 | a = 0; 54 | while (s_1[a] && s_2[a]) 55 | { 56 | if (s_1[a] > s_2[a]) 57 | return (0); 58 | else if (s_2[a] > s_1[a]) 59 | return (1); 60 | a++; 61 | } 62 | if (s_2[a]) 63 | return (1); 64 | else if (s_1[a]) 65 | return (0); 66 | return (0); 67 | } 68 | 69 | int check_array_arrangment(char ***array, int _si) 70 | { 71 | int a; 72 | int b; 73 | int c; 74 | 75 | a = 0; 76 | while (a < _si - 1) 77 | { 78 | b = a + 1; 79 | while (b < _si) 80 | { 81 | c = string_weight_compare(array[a][0], array[b][0]); 82 | if (c || (c < 0 && (b - a) > 1)) 83 | return (0); 84 | b++; 85 | } 86 | a++; 87 | } 88 | return (1); 89 | } 90 | 91 | int is_valid_echo_param(char *s) 92 | { 93 | int a; 94 | 95 | a = 0; 96 | if (s && s[a] && s[a] == '-') 97 | { 98 | while (s[++a]) 99 | { 100 | if (s[a] != 'n') 101 | return (0); 102 | } 103 | } 104 | else 105 | return (0); 106 | return (1); 107 | } 108 | -------------------------------------------------------------------------------- /minishell/src/05_builtin/builtin_commands_utils3.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* builtin_commands_utils3.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/03/04 18:44:36 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:47:08 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void __exit(char **_cmd_) 16 | { 17 | int status; 18 | 19 | status = 0; 20 | if (_cmd_[1] && _cmd_[2]) 21 | status = 1; 22 | else if (_cmd_[1] && !is_string_numeric(_cmd_[1])) 23 | status = 255; 24 | else if (_cmd_[1]) 25 | status = string_to_int(_cmd_[1]); 26 | free_string_array(_cmd_); 27 | exit(status); 28 | } 29 | 30 | int export_print_or_export(char **_cmd_) 31 | { 32 | int a; 33 | 34 | a = 1; 35 | while (_cmd_[0] && _cmd_[a]) 36 | { 37 | if (_cmd_[a]) 38 | return (1); 39 | a++; 40 | } 41 | return (0); 42 | } 43 | 44 | int export_statment_check(char *_cmd_) 45 | { 46 | int a; 47 | int b; 48 | 49 | a = sizeof_str(_cmd_, '='); 50 | if (a > 1 && _cmd_[a - 1] == '+') 51 | a -= 1; 52 | if (a) 53 | { 54 | b = 0; 55 | while (b < a) 56 | { 57 | if (!b && !ft_isalpha(_cmd_[b]) && _cmd_[b] != '_') 58 | return (-1); 59 | else if (b && !ft_isalnum(_cmd_[b]) && _cmd_[b] != '_') 60 | return (-1); 61 | b++; 62 | } 63 | } 64 | return (a); 65 | } 66 | -------------------------------------------------------------------------------- /minishell/src/06_signals/signal_handlers.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* signal_handlers.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:20:26 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 15:43:59 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void setup_signal_handlers(void) 16 | { 17 | signal(SIGINT, handle_ctrl_c); 18 | signal(SIGQUIT, SIG_IGN); 19 | } 20 | 21 | void child_ctrl_c(int sig_num) 22 | { 23 | if (sig_num == 2) 24 | g_var_thing = 130; 25 | else 26 | { 27 | ft_putstr_fd("Quit", 1); 28 | g_var_thing = 131; 29 | } 30 | write(1, "\n", 1); 31 | } 32 | 33 | void handle_ctrl_c(int a) 34 | { 35 | (void)a; 36 | g_var_thing = 1; 37 | rl_replace_line("", 0); 38 | write(1, "\n", 1); 39 | rl_on_new_line(); 40 | rl_redisplay(); 41 | } 42 | -------------------------------------------------------------------------------- /minishell/src/07_env_var_expansion/env_handling.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* env_handling.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/29 06:53:11 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:48:26 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int is_valid_variable_start(char *str, int index, int con) 16 | { 17 | if ((con && str[index] == '$' 18 | && str[index + 1] 19 | && str[index + 1] != '$' 20 | && !ft_isspace(str[index + 1]) 21 | && (ft_isalnum(str[index + 1]) 22 | || str[index + 1] == '_' 23 | || str[index + 1] == '?')) 24 | || (!con && str[index] 25 | && str[index] != '$' 26 | && !ft_isspace(str[index]) 27 | && (ft_isalnum(str[index]) 28 | || str[index] == '_' 29 | || str[index] == '?'))) 30 | return (1); 31 | return (0); 32 | } 33 | 34 | void append_env_var(char *var, t_env *env) 35 | { 36 | int b; 37 | int c; 38 | int d; 39 | int o; 40 | char *env_var; 41 | 42 | c = sizeof_str(var, '+'); 43 | d = sizeof_str(var, '\0') - c - 1; 44 | env_var = malloc(c + 1); 45 | s_strcopy(env_var, var, 0, c); 46 | o = find_env_var_index(env, env_var); 47 | free(env_var); 48 | if (o >= 0) 49 | { 50 | b = sizeof_str(env->original_env[o], '\0'); 51 | env_var = malloc(b + d + 1); 52 | if (!env_var) 53 | return ; 54 | s_strcopy(env_var, env->original_env[o], 0, b); 55 | s_strcopy(env_var + b, var, c + 2, sizeof_str(var, '\0')); 56 | } 57 | else 58 | env_var = str_without_char(var, '+'); 59 | replace_env_var(env_var, env); 60 | free(env_var); 61 | } 62 | 63 | int find_env_var_index(t_env *env, char *name) 64 | { 65 | int a; 66 | 67 | a = 0; 68 | while (env->parsed_env[a] != 0) 69 | { 70 | if (str_cmp(env->parsed_env[a][0], name, NULL)) 71 | return (a); 72 | a++; 73 | } 74 | return (-1); 75 | } 76 | -------------------------------------------------------------------------------- /minishell/src/07_env_var_expansion/env_managment.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* env_managment.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:08:31 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:48:58 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | char **copy_env_exclude_index(char **env, int a, int a_2, int d) 16 | { 17 | char **new_thing; 18 | int b; 19 | int c; 20 | 21 | b = 0; 22 | c = 0; 23 | new_thing = malloc((a + a_2) * sizeof(char **)); 24 | if (!new_thing) 25 | return (NULL); 26 | while (b < a) 27 | { 28 | if (b != d) 29 | new_thing[c++] = strcopy(env[b]); 30 | b++; 31 | } 32 | if (d >= 0) 33 | new_thing[c] = 0; 34 | free_string_array(env); 35 | return (new_thing); 36 | } 37 | 38 | char ***duplicate_env_structure(t_env *env, int a, int a_2, int d) 39 | { 40 | int b; 41 | int c; 42 | char ***new_thing; 43 | 44 | b = 0; 45 | c = 0; 46 | new_thing = malloc((a + a_2) * sizeof(char ***)); 47 | while (b < a) 48 | { 49 | if (b != d) 50 | { 51 | new_thing[c] = malloc(2 * sizeof(char **)); 52 | if (!new_thing[c]) 53 | return (NULL); 54 | new_thing[c][0] = strcopy(env->parsed_env[b][0]); 55 | new_thing[c][1] = strcopy(env->parsed_env[b][1]); 56 | c++; 57 | } 58 | b++; 59 | } 60 | if (d >= 0) 61 | new_thing[c] = 0; 62 | if (a_2 != 'F') 63 | free_environment_variables(env->parsed_env); 64 | return (new_thing); 65 | } 66 | 67 | void remove_env_entry(t_env *env, int c) 68 | { 69 | int a; 70 | 71 | a = 0; 72 | while (env->parsed_env[a] != 0) 73 | a++; 74 | if (a > 0) 75 | { 76 | env->parsed_env = duplicate_env_structure(env, a, 0, c); 77 | env->original_env = copy_env_exclude_index(env->original_env, a, 0, c); 78 | } 79 | } 80 | 81 | void update_env_value_at_index(t_env *env, char *cmd, int a, int con) 82 | { 83 | int b; 84 | int c; 85 | 86 | b = sizeof_str(cmd, '='); 87 | c = sizeof_str(cmd, '\0') - b; 88 | if (con > 0) 89 | { 90 | env->parsed_env[a][1] = malloc(c + 1); 91 | if (!env->parsed_env[a][1]) 92 | return ; 93 | s_strcopy(env->parsed_env[a][1], cmd, b + 1, b + c); 94 | } 95 | else 96 | { 97 | env->parsed_env[a][1] = malloc(3); 98 | if (!env->parsed_env[a][1]) 99 | return ; 100 | if (!con) 101 | env->parsed_env[a][1][0] = '\0'; 102 | else 103 | s_strcopy(env->parsed_env[a][1], "F1", 0, 2); 104 | } 105 | } 106 | 107 | void add_env_entry(t_env *env, char *cmd, int b, int con) 108 | { 109 | int a; 110 | int c; 111 | 112 | a = 0; 113 | c = 2; 114 | if (con) 115 | c = sizeof_str(cmd, '\0') - b; 116 | while (env->parsed_env[a] != 0) 117 | a++; 118 | env->parsed_env = duplicate_env_structure(env, a, 2, -1); 119 | env->original_env = copy_env_exclude_index(env->original_env, a, 2, -1); 120 | env->original_env[a] = malloc(b + c + 1); 121 | env->parsed_env[a] = malloc(2 * sizeof(char *)); 122 | env->parsed_env[a][0] = malloc(b + 1); 123 | if (!env->parsed_env[a] || !env->parsed_env[a][0] || !env->original_env[a]) 124 | return ; 125 | s_strcopy(env->parsed_env[a][0], cmd, 0, b); 126 | if (con > 0) 127 | s_strcopy(env->original_env[a], cmd, 0, sizeof_str(cmd, '\0')); 128 | else 129 | s_strcopy(env->original_env[a], " ", 0, 1); 130 | update_env_value_at_index(env, cmd, a, con); 131 | env->original_env[a + 1] = 0; 132 | env->parsed_env[a + 1] = 0; 133 | } 134 | -------------------------------------------------------------------------------- /minishell/src/07_env_var_expansion/env_managment2.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* env_managment2.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/28 11:53:44 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:49:20 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | void replace_env_var(char *var, t_env *env) 16 | { 17 | int c; 18 | int o; 19 | char *env_var; 20 | 21 | c = sizeof_str(var, '='); 22 | env_var = malloc(c + 1); 23 | if (!env_var) 24 | return ; 25 | s_strcopy(env_var, var, 0, c); 26 | o = find_env_var_index(env, env_var); 27 | if (o >= 0) 28 | remove_env_entry(env, o); 29 | free(env_var); 30 | if (c > 0 && c < sizeof_str(var, '\0') - 1) 31 | add_env_entry(env, var, c, 1); 32 | else if (var[c] == '=') 33 | add_env_entry(env, var, c, 0); 34 | else if (c == sizeof_str(var, '\0')) 35 | add_env_entry(env, var, c, -1); 36 | } 37 | 38 | void update_env_status(t_env *env, int status, char *start) 39 | { 40 | char *var; 41 | int a; 42 | 43 | a = count_digits_in_int(status) + sizeof_str(start, '\0') + 1; 44 | var = malloc(a); 45 | if (!var) 46 | return ; 47 | s_strcopy(var, start, 0, sizeof_str(start, '\0')); 48 | var[--a] = '\0'; 49 | if (!status) 50 | var[--a] = '0'; 51 | while (status) 52 | { 53 | var[--a] = (status % 10) + 48; 54 | status /= 10; 55 | } 56 | replace_env_var(var, env); 57 | free(var); 58 | } 59 | 60 | int is_space(char *line) 61 | { 62 | int a; 63 | 64 | a = 0; 65 | while (line[a] == ' ' || line[a] == '\t' 66 | || line[a] == '\n') 67 | a += 1; 68 | if (line[a] == '\0') 69 | return (1); 70 | return (0); 71 | } 72 | 73 | int check_line(char **line) 74 | { 75 | if (*line[0] == '\0' || str_cmp(*line, "\n", NULL) || is_space(*line)) 76 | { 77 | free(*line); 78 | return (1); 79 | } 80 | return (0); 81 | } 82 | 83 | char *str_without_char(char *str, char del) 84 | { 85 | int a; 86 | int b; 87 | char *new_str; 88 | 89 | a = 0; 90 | b = 0; 91 | new_str = malloc(sizeof_str(str, '\0') + 1); 92 | if (!new_str) 93 | return (NULL); 94 | while (str[a]) 95 | { 96 | if (str[a] != del) 97 | new_str[b++] = str[a]; 98 | a++; 99 | } 100 | new_str[b] = '\0'; 101 | return (new_str); 102 | } 103 | -------------------------------------------------------------------------------- /minishell/src/07_env_var_expansion/variable_expansion.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* variable_expansion.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:17:44 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:50:12 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | char *replace_variable_with_value( 16 | char *old_var, char *__new, int st, int end) 17 | { 18 | int size; 19 | char *new__; 20 | int unsize; 21 | 22 | unsize = sizeof_str(__new, '\0'); 23 | size = st + (sizeof_str(old_var, '\0') - end) + unsize; 24 | new__ = malloc(size + 1); 25 | if (!new__) 26 | return (NULL); 27 | s_strcopy(new__, old_var, 0, st); 28 | s_strcopy(new__ + st, __new, 0, unsize); 29 | s_strcopy(new__ + st + unsize, old_var, end, sizeof_str(old_var, '\0')); 30 | free(old_var); 31 | return (new__); 32 | } 33 | 34 | char *expand_variable_in_string(char *var, t_env *env, int a, int *f_hole) 35 | { 36 | int hole_size; 37 | int c; 38 | int b; 39 | char *new_var; 40 | 41 | b = a + 1; 42 | while (var[a] && is_valid_variable_start(var, b, 0)) 43 | b++; 44 | hole_size = b - a; 45 | new_var = malloc(hole_size + 1); 46 | s_strcopy(new_var, var, a + 1, b); 47 | if (str_cmp(new_var, "?", NULL) && g_var_thing) 48 | update_env_status(env, g_var_thing, "?="); 49 | g_var_thing = 0; 50 | c = find_env_var_index(env, new_var); 51 | free(new_var); 52 | *f_hole = 0; 53 | if (c >= 0) 54 | { 55 | new_var = replace_variable_with_value(var, env->parsed_env[c][1], a, b); 56 | *f_hole = sizeof_str(env->parsed_env[c][1], '\0') + a; 57 | } 58 | else 59 | new_var = replace_variable_with_value(var, "", a, b); 60 | return (new_var); 61 | } 62 | 63 | char *recursively_expand_variables( 64 | char *var, t_env *env, int __con, int *f_arr) 65 | { 66 | char *new_var; 67 | 68 | while (var[f_arr[0]]) 69 | { 70 | if (var[f_arr[0]] == 39) 71 | { 72 | f_arr[0]++; 73 | f_arr[1]++; 74 | while (!(f_arr[2] % 2) && var[f_arr[0]] && var[f_arr[0]] != 39) 75 | f_arr[0]++; 76 | } 77 | if (var[f_arr[0]] == 34) 78 | f_arr[2]++; 79 | if (is_valid_variable_start(var, f_arr[0], 1) 80 | && ((!(f_arr[2] % 2) && __con) || (f_arr[2] % 2 && !__con))) 81 | return (new_var = expand_variable_in_string( 82 | var, env, f_arr[0], &f_arr[0]), 83 | recursively_expand_variables(new_var, 84 | env, __con, f_arr)); 85 | f_arr[0]++; 86 | } 87 | return (var); 88 | } 89 | 90 | char **refactore_args_array(char **args, int *quick_norm_fix) 91 | { 92 | int a; 93 | int b; 94 | int c; 95 | char **new_args; 96 | 97 | a = 0; 98 | b = 0; 99 | *quick_norm_fix = 0; 100 | c = count_strings_in_array(args); 101 | new_args = malloc((detected_flaws(args) + c + 1) * sizeof(char **)); 102 | if (!new_args) 103 | return (NULL); 104 | while (args[a]) 105 | { 106 | c = is_flawed_str(args[a], 0, 0, 0); 107 | if (c) 108 | b = simplified_refactor_thing(new_args, b, args[a], 0); 109 | else 110 | new_args[b++] = strcopy(args[a]); 111 | a++; 112 | } 113 | new_args[b] = 0; 114 | free_string_array(args); 115 | return (new_args); 116 | } 117 | 118 | void expand_variables_in_ast(t_ast_node *head, t_env *env) 119 | { 120 | int a; 121 | int f_arr[3]; 122 | 123 | if (head->file_type != FILE_READY && head->args 124 | && head->file_type != READ_FROM_APPEND) 125 | { 126 | a = -1; 127 | while (head->args[++a]) 128 | ((ft_memset(f_arr, 0, 3 * sizeof(int))), 129 | (head->args[a] = recursively_expand_variables( 130 | head->args[a], env, 1, f_arr))); 131 | head->args = refactore_args_array(head->args, &a); 132 | while (head->args[a]) 133 | { 134 | ft_memset(f_arr, 0, 3 * sizeof(int)); 135 | head->args[a] = recursively_expand_variables( 136 | head->args[a], env, 0, f_arr); 137 | head->args[a] = remove_quotes_from_str(head->args[a], 0, 0, 0); 138 | a++; 139 | } 140 | } 141 | if (head->left) 142 | expand_variables_in_ast(head->left, env); 143 | if (head->right) 144 | expand_variables_in_ast(head->right, env); 145 | } 146 | -------------------------------------------------------------------------------- /minishell/src/07_env_var_expansion/variable_expansion_utils.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* variable_expansion_utils.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/03/03 08:59:59 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:50:57 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int simplified_refactor_thing(char **array, int index, char *str, int in) 16 | { 17 | int size; 18 | 19 | if (!str[in] || in > sizeof_str(str, '\0')) 20 | return (index); 21 | while (str[in] && str[in] == ' ') 22 | in++; 23 | size = sizeof_str(str + in, ' '); 24 | if (size > sizeof_str(str + in, 34)) 25 | size = sizeof_str(str + in, 34); 26 | if (size > sizeof_str(str + in, 39)) 27 | size = sizeof_str(str + in, 39); 28 | if (str[in] == 34) 29 | size = sizeof_str(str + in + 1, 34) + 2; 30 | if (str[in] == 39) 31 | size = sizeof_str(str + in + 1, 39) + 2; 32 | if ((in + size) > sizeof_str(str, '\0')) 33 | return (index); 34 | array[index] = malloc(size + 1); 35 | if (!array[index]) 36 | return (index); 37 | s_strcopy(array[index], str, in, in + size); 38 | return (simplified_refactor_thing(array, index + 1, str, in + size)); 39 | } 40 | 41 | int sus_getit_right(char *str, int s_q, int d_q) 42 | { 43 | int a; 44 | 45 | a = 0; 46 | (void)s_q; 47 | while (str[a]) 48 | { 49 | if (str[a] == 34 || str[a] == 39 50 | || str[a] == '$') 51 | d_q++; 52 | a++; 53 | } 54 | return (d_q); 55 | } 56 | 57 | int is_flawed_str(char *str, int a, int b, int res) 58 | { 59 | int si_q; 60 | int do_q; 61 | 62 | si_q = 0; 63 | do_q = 0; 64 | while (str[a]) 65 | { 66 | if (str[a] == 34) 67 | do_q++; 68 | else if (str[a] == 39) 69 | si_q++; 70 | else if (!(si_q % 2) && !(do_q % 2)) 71 | { 72 | if (str[a] == ' ') 73 | { 74 | if (b) 75 | res++; 76 | b = 0; 77 | } 78 | else 79 | b = 1; 80 | } 81 | a++; 82 | } 83 | return (res); 84 | } 85 | 86 | int detected_flaws(char **array) 87 | { 88 | int a; 89 | int res; 90 | 91 | res = 0; 92 | a = 0; 93 | while (array[a]) 94 | { 95 | res += is_flawed_str(array[a], 0, 0, 0); 96 | res += sus_getit_right(array[a], 0, 0); 97 | a++; 98 | } 99 | return (res); 100 | } 101 | -------------------------------------------------------------------------------- /minishell/src/main.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* main.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: zelhajou +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/17 18:00:12 by zelhajou #+# #+# */ 9 | /* Updated: 2024/03/10 15:37:59 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | t_token *process_and_tokenize_input(char *input) 16 | { 17 | char *trimmed_input; 18 | t_token *tokens; 19 | 20 | trimmed_input = ft_strtrim(input, " \t\n\v\f\r"); 21 | free(input); 22 | if (!trimmed_input) 23 | return (NULL); 24 | if (syntax_error_checker(trimmed_input)) 25 | { 26 | free(trimmed_input); 27 | return (NULL); 28 | } 29 | tokens = tokenize_input(trimmed_input); 30 | free(trimmed_input); 31 | return (tokens); 32 | } 33 | 34 | void main_shell_execution_loop(t_env *env) 35 | { 36 | char *line; 37 | int status; 38 | t_token *tokens; 39 | t_ast_node *ast; 40 | 41 | while (1) 42 | { 43 | status = 0; 44 | line = readline("> "); 45 | if (!line) 46 | break ; 47 | if (check_line(&line)) 48 | continue ; 49 | add_history(line); 50 | tokens = process_and_tokenize_input(line); 51 | if (!tokens) 52 | status = 258; 53 | if (!status) 54 | { 55 | ast = parse_tokens(&tokens); 56 | command_execution_manager(ast, env, &status); 57 | free_ast(ast); 58 | } 59 | update_env_status(env, status, "?="); 60 | } 61 | } 62 | 63 | int main(int argc, char **argv, char **original_env) 64 | { 65 | t_env *env; 66 | 67 | (void)argv; 68 | setup_signal_handlers(); 69 | env = malloc(sizeof(t_env)); 70 | if (!isatty(1) || !isatty(0)) 71 | return (free(env), 0); 72 | if (argc == 1 && initialize_shell_with_environment(env, original_env)) 73 | { 74 | main_shell_execution_loop(env); 75 | cleanup_and_exit_shell(env, 0); 76 | } 77 | return (0); 78 | } 79 | -------------------------------------------------------------------------------- /minishell/src/utils/shell_utilities.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* shell_utilities.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:20:49 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:51:45 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int get_shell_exit_status(int err) 16 | { 17 | if (err == 2) 18 | return (127); 19 | else if (err == 13) 20 | return (126); 21 | return (err); 22 | } 23 | 24 | int count_digits_in_int(int num) 25 | { 26 | int a; 27 | 28 | a = 0; 29 | if (!num) 30 | return (1); 31 | while (num) 32 | { 33 | num /= 10; 34 | a++; 35 | } 36 | return (a); 37 | } 38 | 39 | void free_environment_variables(char ***array) 40 | { 41 | int a; 42 | 43 | a = 0; 44 | while (array[a]) 45 | { 46 | free(array[a][0]); 47 | free(array[a][1]); 48 | free(array[a]); 49 | a += 1; 50 | } 51 | free(array); 52 | } 53 | 54 | void cleanup_and_exit_shell(t_env *env, int status) 55 | { 56 | if (env) 57 | { 58 | free_string_array(env->original_env); 59 | free_environment_variables(env->parsed_env); 60 | free(env); 61 | } 62 | exit(status); 63 | } 64 | 65 | void close_pipe_ends(int fd1, int fd2) 66 | { 67 | close(fd1); 68 | close(fd2); 69 | } 70 | -------------------------------------------------------------------------------- /minishell/src/utils/string_utilities/string_utils.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* string_utils.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/29 06:51:24 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:52:16 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | char *remove_quotes_from_str(char *str, int si_q_c, int do_q_c, int a) 16 | { 17 | char *new_str; 18 | int b; 19 | 20 | b = 0; 21 | new_str = malloc(sizeof_str(str, '\0') + 1); 22 | while (str[a]) 23 | { 24 | if (str[a] == 34 && !(si_q_c % 2)) 25 | do_q_c++; 26 | else if (str[a] == 39 && !(do_q_c % 2)) 27 | si_q_c++; 28 | if ((str[a] != 34 || si_q_c % 2) 29 | && ((str[a] != 39) || do_q_c % 2)) 30 | new_str[b++] = str[a]; 31 | a++; 32 | } 33 | new_str[b] = '\0'; 34 | return (free(str), new_str); 35 | } 36 | 37 | char *strcopy(char *src) 38 | { 39 | int a; 40 | int b; 41 | char *dest; 42 | 43 | b = 0; 44 | while (src[b]) 45 | b += 1; 46 | dest = malloc(b + 1); 47 | if (!dest) 48 | return (NULL); 49 | a = 0; 50 | while (a < b) 51 | { 52 | dest[a] = src[a]; 53 | a += 1; 54 | } 55 | dest[a] = '\0'; 56 | return (dest); 57 | } 58 | 59 | void s_strcopy(char *s_1, char *s_2, int st, int en) 60 | { 61 | int a; 62 | 63 | a = 0; 64 | while (st < en) 65 | s_1[a++] = s_2[st++]; 66 | s_1[a] = '\0'; 67 | } 68 | -------------------------------------------------------------------------------- /minishell/src/utils/string_utilities/string_utils2.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* string_utils2.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: beddinao +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/02/27 10:14:59 by beddinao #+# #+# */ 9 | /* Updated: 2024/03/10 09:52:47 by beddinao ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "minishell.h" 14 | 15 | int sizeof_str(char *str, char end) 16 | { 17 | int a; 18 | 19 | a = 0; 20 | while (str && str[a] != '\0' && str[a] != end) 21 | a += 1; 22 | return (a); 23 | } 24 | 25 | int str_cmp(char *s_1, char *s_2, char *s_3) 26 | { 27 | int a; 28 | 29 | a = 0; 30 | while (s_1[a] && s_2[a] && s_1[a] == s_2[a]) 31 | a += 1; 32 | if (a == sizeof_str(s_1, '\0') 33 | && a == sizeof_str(s_2, '\0')) 34 | return (1); 35 | if (s_3) 36 | return (str_cmp(s_1, s_3, NULL)); 37 | return (0); 38 | } 39 | 40 | int string_to_int(char *str) 41 | { 42 | int num; 43 | int a; 44 | 45 | num = 0; 46 | a = 0; 47 | while (str[a]) 48 | { 49 | if (str[a] <= '9' && str[a] >= '0') 50 | num = (num * 10) + (str[a] - 48); 51 | a++; 52 | } 53 | return (num); 54 | } 55 | 56 | int count_strings_in_array(char **arr) 57 | { 58 | int a; 59 | 60 | a = 0; 61 | while (arr[a] != 0) 62 | a++; 63 | return (a); 64 | } 65 | 66 | void free_string_array(char **arr) 67 | { 68 | int a; 69 | 70 | a = 0; 71 | while (arr[a] != 0) 72 | { 73 | free(arr[a]); 74 | a += 1; 75 | } 76 | free(arr); 77 | } 78 | --------------------------------------------------------------------------------