How the shell works when you write and enter -ls -l?

What is a shell?

A shell is software that provides an interface for an operating system’s users to provide access to the kernel’s services.

On Unix-based or Linux-based operating systems, a shell can be invoked through the shell command in the command line interface (CLI), allowing users to direct operations through computer commands, text or script.

Shells also exist for programming languages, providing them with autonomy from the operating system and allowing cross-platform compatibility.

What does ls -l * .c do?

  • ls : The ls command shows us the files and directories that we have within the directory in which we are. This is what it shows us in the terminal:
  • l : It shows all the information: user, group, permissions, size, date and time of creation. This is what it shows us in the terminal:
  • *.c : The “ * ” tells the shell that we want all the files, but with the “ .c ” we tell it that we only want all the files that contain the extension “ .c ” at the end. This is what it shows us in the terminal:

But what is behind all this? How can the shell do that?

  1. Shell prompt is displayed.

the shell is an infinite loop that keeps running until an exit command or end-of-file (EOF) value is sent. The shell prompt typically displayed is a $ as seen below

In the gif above, what is going on is that the shell is ready and waiting to receive a command after the $.

2. The command entered will be read by the shell.

The shell reads the command from standard input using the getline()function which saves the line written by the user from stdin in a buffer, including the newline character.

3. Tokenizes the line of commands entered by the user.

Tokenization is called to the functionality provided by strtok(). This helps us to divide the line entered by the user into tokens, this happens thanks to the fact that it gives us the facility to choose a delimiter that must be a “ ” (space) with the delimiter, we split our line into tokens for each written command. These tokens are typically stored in an array of strings with a terminating NULL pointer for accurate parsing.

ls\0 -l\0

4. Search the command entered by the user in the enviroment.

The command will be looked for in the enviroment list to execute it as an environment variable, for this we will use extern char ** environment; (man environment), if the command does not belong to an environment variable, it will search inside the PATH

5. Search in the PATH the command entered by the user.

If the command entered by the user is not found within the environment, it will proceed to search for it in the PATH. For this we need to locate the “PATH” in the environment and tokenize the directories using a delimiter for the “:”, and thus be able to put our command /ls at the end of each directory path to verify if it exists.

If it exists, we go to the next step where we will use the fork () function to create a child process.

6. The child process is created for the execution of the program.

We will use the fork () command. to create the child process, which will run the program with the location of the directory where the executable was found. The child employs the execve() function which takes the executable (/bin/ls), the array of tokens ({“/bin/ls”, “-l”, NULL}), and an optional environment argument (usually NULL) to run the executable.

8. The memory is freed and returns from the beginning where the prompt $ was shown.

To finish, frees any allocated memory with the function free () and initiates another iteration of the main shell loop (while). And it will redisplay the prompt $.

--

--