What the shell?! — ls -l
An overview
Have you ever see those hacker videos where they type weird words on a computer and suddenly everything starts popping, writting and flashing colors (eventhough real hacking isn’t as flashy as this)? well, if you have (or haven’t) I’ll tell you there’s no big mistery about their actions, they’re just communicating with the computer through a CLI (command line interface), different from GUI (graphical user interface).
CLI’s work by typing and entering certain words (commands) that execute certain behaviors (system calls), both CLI and GUI serve the same purpose, they’re a tool for humans to communicate with the computer. I.E
File creation — CLI
$ touch newFile
File creation — GUI
- Right click
- New file
- Enter name (newFile)
Who determines the behavior of command is the Kernel that controls the Operative System and receives a command from the Shell typed by the user in the terminal. Confused? stay with me.
What the shell is all of this?!
As said above, the user communicates with the computer via CLI terminal, (that scary screen hackers use) then they type a command and when enter is pressed, that command is sent to the shell. Here is where the fun begins.
Shell
A Shell it’s an environment in which we can run our commands, programs, and shell scripts. When a program finishes executing, it displays that program’s output. On most Linux systems a program called bash (which stands for Bourne Again SHell, an enhanced sh, written by Steve Bourne).
Operating System
An Operating System (OS), generally, is software that allows a user to run other applications on a computing device. Linux Operating System has primarily three components:
- Kernel − Kernel is the core part of Linux. It consists of various modules and it interacts directly with the underlying hardware.
- System Library − System libraries are special functions or programs using which application programs or system utilities accesses Kernel’s features.
- System Utility − System Utility programs are responsible to do specialized, individual level tasks.
Kernel
The Kernel is the central module of an OS. It is the part of the operating system that loads first. Typically, the kernel is responsible for memory management, process and task management, and disk management. The kernel connects the system hardware to the application software. Every operating system has a kernel.
With this knowledge, we’ll delve in an example by typing
the command “ls -l” and cover step by step it’s process, so be sharp!
The whole process of ls -l
1. Typing out the command
In our CLI, a prompt ($) will be displayed waiting for the user’s input, this input is the standard input that is any information given by the keyboard to the shell when pressing enter. I.E
vagrant@vagrant-ubuntu-trusty-64:~$ ls -l
2. Catching & storing the command
The written command “ls -l” will go from the standard input (stdin)to a function called getline() function , it catches an entire line from stdin, storing the address of the buffer (line in this case) containing the text. I.E
line = "ls -l"
3. Converting line into tokens
line will be converted into tokens thanks to strtok() function, it parses a string into a sequence of tokens by delimiting a string, delimiters can be any character you want. I.E when delimiter is a space (between ls and -l) “ ”
line = ls -lls
-l
In this case, line has two parts ls and -l , so it will break line into two tokens, one containing ls and the other -l. I.E
token[0] = ls
token[1] = -l
4. Checking token’s accessibility
First of all, we have to know that the shell has external command like “ls” and builtin commands like “cd”, builtin commands are innate of the shell, external commands need to be located first and then executed, the external commands location is the PATH. I.E
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
PATH it’s an environmental variable in Linux used to know which directories to search for executables files. I.E
- The command “ls” is located inside the directory /bin/ls
- The command “cd” is a shell builtin.
Secondly, we concatenate every directory inside path with our command stored in the first token by using strcat() function, then we ask through access() syscall, that checks whether the calling process can access the file pathname and returning the accessed path. I.E
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/gamesusr/local/sbin/ls
usr/local/ls
binusr/sbin/ls
usr/bin/ls
sbin/ls
bin/lsbin/ls -> ls can access the file in /bin/ directory
If the command does not exist in PATH and if it is not a builtin command an error message will be printed. I.E
vagrant@vagrant-ubuntu-trusty-64:~$ errorcomm
hsh: 1: errorcomm: not found
5. Command execution
To execute an external command we have to create another parallel process with fork() function, it creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process.
The parent must wait for its child to finish using the wait() syscall, it suspends execution of the calling process until one of its children terminates. The child uses excve() function, it executes the program referred to by pathname, the accessed path. It’ll print the results in our terminal.
After waiting its child, the parent resumes its process, so the prompt ($) will be printed again, allocated memory will be fred and the shell will be ready for another cycle.
There are many things happening under the hood, understanding how a simple command like “ls” works, it really enhances the experience of an engineer by knowing the macro and the micro of things.
Hope you find this story useful, happy coding ;)!