UNIX LS COMMAND Part 2

Marco Niño
4 min readNov 28, 2019

Here we are again, trying to explain the way the command “ls” works inside Unix. This time we’ll take another aproach to it, looking at the insides of the execution of the command in the shell.

First with the concepts basics about the shell, it’s a program that provides the traditional text-only user interface, that takes the commands and provides them to the operating system to execute.

When we start the shell, it will start up all the configuration files to get it ready to work, later it will create a prompt to tell you the system is ready to execute commands:

Every shell has its prompt

The next thing to do is write the command in the prompt to tell the computer what we want to execute:

A simple command with a simple flag

Then the output would be:

A few directories to show

It shows all the elements (directories, files, executables, etc.) inside of the current working directory. But the question is: What does the machine do to show all that info?

A simple explanation can be found in another story but this time we’ll go a little bit deeper.

First, the machine needs to read whatever the user writes in the screen, to do that it uses a system call named getline, it stores what the user inputs inside a buffer (char *buffer), then it needs to parse the text introduced to determine it has the correct syntax or if the command exist in the first place:

Watch your syntax!

Later, the shell will determine the location of the command the user input, to do this it refers to the Environment Variable (envar): “PATH”. An environment variable is, in escense, a variable that controls the behavior of the environment of the system; you can check your envars by using “env”:

May the env guide thy PATH

The PATH is a variable which cointains a list of folders separated by a colon (:), the system will look at each one of these folders to see if the inputed command is in one of them; if the command is in one of the folders, the inputed command is separated in tokens as such: <ls> <-l>. This is done for the machine to use the system call “execve” which creates a new process to execute the command.

When the system calls execve the parent process (prompt) creates a new child process (execute command), and thus the parent is set to wait for its son to finish executing.

Execution process if we type “ls -l” in c:

  • Receive input from user:

With the prompt ($) input “ ls -l”to the command line and shell reads the input by using getline.

  • Verification alias and wildcards.

The shell verify all the alias and a wildcards is a character that can be used as a substitute for any of a class of characters in a search, thereby greatly increasing the flexibility and efficiency of searches. One of the most used wildcards is the star or asterisk wildcard “*”.

For the aliases, the shell will look at the .bashrc hidden file to see what aliases are defined for the system, and as a matter of fact, ls is an alias itself, it stands for “ls — color=auto” (that’s with a double dash).

  • Verification Built-in.

Next, the shell will look at the stored built-ins to execute, a built-in is a command integrated inside the shell.

  • Verification PATH.

The shell will try to execute the command right away but it can fail if the command is not directed by a filepath, in that case, the shell will look at the PATH (an envar), and change the name of the command to include the path.

  • Program execution in the child process if file exits.

If the file exist within the path, the shell will execute it by creating a child process with the system call (syscall) “fork()”; this syscall will create a new process with it’s own PID passed to the “father” process. The creation of a child is needed so the parent (the shell) will not be terminated when the execution of the program ends.

  • Completion of the child process and output printing to user.

The child process will carry the task of executing the process while its parent waits for it, the child then prints the output of the command to the standard output in accordance to the command’s directives, then it will proceed to self-terminate to let its father continue with the clean-up.

When the child process is terminated, the parent process is repeated and we get a new iteration of the prompt, and then again, the system is waiting for a new command to execute.

And now it waits…

--

--