And what happend when you type <ls -l> on your bash prompt.

Alexis Oreiro
5 min readNov 25, 2020

The first thing to know is that a Unix Shell is a command language interpreter (command execution program). The primary purpose of which is to translate command lines typed at a terminal into system actions. The shell itself is a program through which other programs are invoked.

This program was created by Bill Joy at the University of California at Berkeley as an alternative to Unix original shell, the Bourne shell.

The C shell typically runs in a text window, allowing the user to type commands. The C shell can also read commands from a file, called a script. Like all Unix shells, it supports filename wildcarding, piping, command substitution, variables and control structures for condition-testing and iteration. What differentiates the C shell from others, is its interactive features and overall style. Its features make it easier and faster to use. The overall style of the language is more readable than previous versions.

Above it is an example of bash prompt.

What is a Script?

One handy thing you can do with the shell is to use standard UNIX commands as building blocks to create your own new commands. To do this, you write a `shell script’, which can contain a number of commands, and then the file can be executed as one command.

Following is an example of a very simple shell script, which gives a brief indication of the types of things you might do.

But what happens when you type ls -l?

The “ls” is a C shell command that is used to print all files and directories in the current directory as a list.

The ls -l option command displays all the files and directories in the current working directory. It also shows respective permissions, size, owners, and the date they were created.

But what really happens when you hit the enter is so much fun!

After you type your command, the shell reads what you typed using the getline function.

The getline function reads the entered line as one string, from the standard input and stores it in a buffer.

The getline() function is prototyped in the stdio.h header file. Here are the three arguments:

&buffer is the address of the first character position where the input string will be stored. It’s not the base address of the buffer, but of the first character in the buffer. This pointer type (a pointer-pointer or the ** thing) causes massive confusion.

&size is the address of the variable that holds the size of the input buffer, another pointer.

stdin is the input file handle. So you could use getline() to read a line of text from a file, but when stdin is specified, standard input is read.

After reading the line and storing it in the buffer, the getline returns an int/ssize_t which is equal to:

  1. The number of characters read, on success, without including the terminating null byte of the string.


2. Prints -1, on failure to read a line (including end-of-file condition).

N.B The programmer must free the allocated memory of the buffer at the end of the program.

Then a string tokenization function is called which splits the command line into tokens. In our shell, we used a function called strtoken() which took the line to tokenize and the delimiter to define token boundaries.

The Shell will then check if ls has any aliases associated with the command you entered. If any aliases are found it will expand that alias before running the command and check if the word of the command entered is a built-in command. Next, it will check for special characters such as: “, ‘, \, *, &, # and runs the logic associated with the special character.

(To execute our command we use the syscall execve.)

The next step is to check if any token is a built-in function. Since built-in functions are treated differently by shell voluntarily. For example cd, echo, help are all built-in commands.

If it’s not a built-in function, we will go to find the PATH variable in the directory. Since it holds the absolute paths for all the executable binary files. Each location specified in the PATH variable is separated using the delimiter : and searches recursively by appending the command at the end of the path.

The C-shell will look through each directory separated by a “:” to see if the ls command exist in each of the directories. If the first word of the command doesn’t exist, an error message would be outputted saying that command does not exist. To execute ls, three system calls are made:


These system calls are made to the kernel to perform a task.

These system calls are made to the Kernel to perform a task. To create a new process that runs commands, the system call fork() is made to create an exact duplicate of the parent process that is now the child of the parent process.

When the system call to fork() is made the child also loads the same program as the parent.

The system call execve() is made and it performs the following task:

The OS stops the duplicated process of the parent and loads up the new program, in this case ls, and loads the new program of ls. the system call execve() replaces parts of the current process with the new loaded program from the ls exe file.

What the system call wait() will do is wait until the command process is completed by the child process befor exiting back to the command prompt of shell.

If the program is executable, the system call execve() to run and execute the program in the child process.

After all is done the shell executes commands to frees up the memory, exits, and reprompts the user for the next input by recalling the enviromental variable prompt string one.

If a command can not be foud, and error will appear and re-prompt the user to enter a command again.

$exit : Terminates the process with an exit status.



Alexis Oreiro

Working to succeed in Cyber Security.