What happens when you type ls -l in the shell

First things first
This article is written based on the experience that we(Andres Campo and Andres González) had with building our own version of a shell for a software development school project.
It can be confused since all of the following terms are directly connected: shell, terminal, kernel, OS, etc. But let me assure you that all of them are independent concepts that work in a different way. But today, we will just focus on the shell, so what is a shell?
Basically is a program that will receive an instruction from the user through the standard input(it could be from the keyboard) and execute a program according to the instruction given.
ls -la
When a software development student or beginner starts using Linux for the first time, the first command to learn is “pwd” to show the current working directory and “ls”, this last one will show you and list all the files and directories located in the current working directory. And everything is magically set up to just to type “ls” so it will show you immediately all the files and directories. But…that’s it? do they appear just because? of course not! there are some complex processes happening under the hood to make it happen. All this includes system calls, loops, memory management, and allocation, data structures as arrays or linked lists, child and parent process created, among other more detailed work that we will explain step by step in the next lines having in mind the process we made to built our own version of a shell. And if you are wondering, yes everything will be written in C language.
The prompt
Simply, the prompt is an indicator of the shell that tells you it is waiting for you to receive an instruction
Receiving a command or instructions from the tty
The shell program will receive the instructions in two ways. First, the interactive mode, which means that the user will interact directly with the program through a TTY(Teletype application), there the user will literally type a command or an instruction to perform. The other way would be to pass an instruction through the non-interactive way, meaning that it won’t be typed but passed through a pipeline or such.
Now, we propose to use the function getline to receive these instructions, giving. Among the address of the size input and the stdin file as arguments, we will pass a memory direction so the getline will save what the user will type into that direction. If we want, we could assign the result of this function to one single variable. It will be of type char.

As the variable name mentions, the buffer already has some space in memory for this, so at this point, there should not be any memory issue at this point(we are just beginning!)
Tokenize!

Now that we already have the user instructions we should “analyze” what did they give to us. To do so, we will tokenize or split the string in several parts having mind delimitators. Those delimitators could be for example, the followings “ ,!¡¿?\’\”\n\t”.
With the function strtok we will divide this string into tokens. How does it work? it will find a delimitator in the string and will replace it with a null character. In that sense, we will have at the end an array of strings. In the next steps, we will analyze what represents each string.
Of course, each string tokenized and the array will have a memory allocation with malloc.
Path and environ
Now that we have the raw material ready, we can go ahead and compare it to our PATH. The PATH is the environment variable that has all the addresses of the programs that can be executed. Now we will tokenize the content of PATH as well. Why? so we can compare the command from the user(already tokenized) with each position of the PATH.
But wait, how do we access the PATH? simply: with the external variable environ.
Since we have tokenized the command ls -la the path will take the -la into account to apply the flags of the program to be executed.
Execution and child process
Let’s imagine that it found a coincidence. The idea right now is to create a new process with the command fork, and a child process will now exist. In this child, the process will be executed on the path that already has the corresponding address. In the case of our example ls -la it will list the files in the current working directory.
Now with the conditionals, we should give to them we will let them know that once the process finishes its execution, the child process will finish as well and will return to the parent process(the regular state where we will wait for another instruction from the user)
Free the memory!
Even if you found a coincidence or not in your PATH with the instructions given by the user, you must free the memory, so remember the memory allocations you made for your array of strings? well, even if the program goes back to the loop or the user exits the program, you must free those arrays of strings.