Imabe source: https://d2uusema5elisf.cloudfront.net/courses/30-days-of-webdev/day-04/public/assets/pistachio.png

A short trip inside the shell

Oscar Angel
7 min readApr 14, 2021

--

The next blog will explain in detail, what happens when you type a command as ls -l *.c in the shell. But before entering into the subject, it is important to first understand what a shell and a terminal is.

What is a Shell?

A shell is a command interpreter program that uses the operating systems services by passing commands typed by the user or a program. In other words, it takes commands from the keyboard and gives them to the operating system to be processed, the results are shown on the terminal screen as standard output or standard error.

Image source: (Shell Scripting Tutorial: How to Create Shell Script in Linux/Unix, 2021

The reason it is named “shell” is because it operates as an external layer of the operating system, protecting it from any damage by the user. The way users interact with a shell can be done through a command-line interface, such as the shell (E.g: sh, bash, zsh, etc…) or by graphical user interface, depending on the computer and the type of operations being performed. (Learning the Shell, 2021).

The main difference between these two relies on how the user interacts with the operating system, which can be done by using graphical elements (GUI), such as windows, icons, text boxes, etc.. , or by commands entered by the user (CLI) (Learning the Shell, 2021). Other differences in memory requirements, speed, customizability and flexibiliyt can also vary. See more detail in the diagram below (Lithmee, 2018).

Image source: (Lithmee, 2018)

Old days and new days of the computer Terminals

The history of the computer terminal can be traced back with the invention of the teletypewriter, teleprintes or TTY. These were electromagnetic devices used to send and receive typed messages through multiple communication channels. Mainly used in telegraphy, in the earliest 1887. Later, hard-copy terminals, like the Teletype Model 33 (1963) and the IMB 2745 (1965), appeared as an evolution of their previous teleprintres, and were devices connected to computers used for entering data into, and “printing” data out. In the next few years, terminals are going to keep improving, some are going to be built-in with microprocessors called “intelligent terminals” and others will have screens. We can say that the end of the era of computer terminals came with the invention of computers for personal use. Here, terminals were no longer needed, and emulated terminals could be found integrated in these machines (Roberts, 2014).

Teletype teleprinter in use in England during World War II. Image source: (Wikipedia, 2021)

As we said before, computers today are personal machines, and they come with terminal emulators, which is no more than a software that emulates a text terminal. This one, operates by sending input typed text (commands or instructions) from the keyboard, so they can be processed by other programs and the operating system, giving as a result an standard output and standard error, displayed on the terminal screeen.

Process of a typical text terminal. xt terminal. Image source (Wikipedia, 2021

Now having in mind what a shell and a terminal are, next it will be described in single steps what happens when typing ls -l *.c in the shell in general terms.

General shell operation

Data entry process

After the commands are entered, the shell checks for file names, aliases, , or variables containing any value, replacing them with its value already stored in memory. For example, if the variable $PATH was entered as a command, its value would be replaced with the list of the directories of the environment. In our ls -l *.c example, the wild card (*) replaces *.c with a list of all the files in the current directory ending with .c. The aim of this step is to organize all arguments, names and files with their representative values.

Search and execute

Now, with the list of arguments organized in the command line with their actual values, the first word is the command that is actually the name of the executable file, and the rest are held as arguments related to the command. This string, composed by the command and its arguments, is fragmented into tokens with strtok(), and stored in an array of pointers where the command, ls will correspond to position 0 of the array. Then, shell checks if argv[0] exists as a built-in. If there is a match between the command name, and the built-in function, this is automatically executed.

Now, before going any further, it is important to understand what built-in and syscalls are in computing. The first one, refers to commands or functions which are integrated within the shell program and are directly executed without any external executable program (The Open Group Base Specifications Issue, 2018). The next one, refers to the syscalls or calls made to the kernel to perform an specific function. Examples of these are open(), fork(), read(), write().

Now, in case either of the above happens, the shell looks for the command on the PATH, which is an environment variable, containing all the directories where the executable files or ready-to-run programs are found. Also, it is relevant to mention that this is possible to happen because the environment variables where previously copied and passed to the program through the **envp found as a parameter in the main (The Linux Information Project, 2006). If a match is successful, the shell file is executed with execve(), but before, a new process known as “child” is generated using the syscall fork() so the shell is not “killed” when execve() runs the file. Then, the “parent” process will wait() until it receives the signal of the execution status of the “child”, in order to continue. This enables the program to keep running in the interactive-mode, where the user can execute or run commands indefinitely until an exit() or EOF (Ctrl + d) signal is detected.

In our example, the command ls is found in the directory path /bin/ls, and therefore is executed with the flag -l which is passed as an argument to the command and with all the filenames ending with .c as parameters.

Finally, after ls is done, the results are shown in the standard output, the prompt $ is printed again using PS1, and the program waits for the new command with getline() .

Now, before continuing, it is important to highlight that there are many types of shells, and each operates in different ways. The previous example, represents our general understanding of how the BASH Shell works when the command ls -l *.c is entered. Next, it will be shown how our shell performed in general terms.

Our shell operation

Once our shell is executed, the isatty() function tests whether the program is a shell or not. Now, this shell can be operated in two modes: interactive mode and non-interactive mode. Inside the interactive mode, isatty()==1, prompt $ is displayed, and the user can execute or run commands indefinitely until an exit() or EOF (Ctrd + d) signal is detected. On the other hand, in the non-interactive mode isatty()==0, commands can only be executed once and prompt is never shown.

Now, once the ls -l is entered, the function getline() reads the commands entered with the syscall read() performed under the hood, and stores the address of the buffer containing the pointer to the command string. Then, the command strings are arranged into an array, and breaked in tokens with the strtok() function. If the command arg[0] (which also represents the file name) does not contain the absolute path of the executable file, it is checked if it belongs to the built-in function of the shell. If not, then the command is searched in the PATH and if found is executed with execve(). But before, a child process is generated with a fork() function so the shell is not killed when the file is runned Finally, results are printed to the standard output, the prompt $ is printed again and the program waits for new commands to be entered.

Image source: Authors

By the way, if you are building a shell and in the process you create a fork bomb by accident in the middle of the night, just remember to… “matanga dijo la changa, because listanga is an holanda from the melo caramelo, lelo lelo lelo…”.

Authors: William Rodriguez, Adriana Echeverri, and Oscar Angel

Bibliography

catb.org. (n.d.). Shell. catb.org. http://www.catb.org/jargon/html/S/shell.html

Lawyer, D. S. (2006, 12 01). Text-Terminal-HOWTO. linux.die.net. https://linux.die.net/HOWTO/Text-Terminal-HOWTO-1.html

Learning the Shell. (2021, — -). linuxcommnd.org. http://linuxcommand.org/lc3_lts0010.php

The Linux Information Project. (2006, 6 2). PATH Definition. info.org. http://www.linfo.org/path_env_var.html

Lithmee. (2018, 07 19). Difference Between GUI and CLI. Pediaa.com. https://pediaa.com/difference-between-gui-and-cli/

The Open Group Base Specifications Issue. (2018, 01 01). Shell & Utilities: Detailed Toc. pubs.opengroup.org. https://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html

Roberts, S. (2014, 0 0). The Distant Writing. distantwriting.co.uk. http://distantwriting.co.uk/index.htm

Shell Scripting Tutorial: How to Create Shell Script in Linux/Unix. (2021, 03 03). Guru99.com. https://www.guru99.com/introduction-to-shell-scripting.html

Shotts, W. (2019). The Linux Command Line (Fifth Internet Edition ed.). A LinuxCommand.org Book. 19.01A

Wikipedia. (2021, 04 21). Teleprinter. Wikipedia. https://en.wikipedia.org/wiki/Teleprinter

--

--