We may wish to read the source code of our Linux tools to understand how they work. This may be because we need to write something similar, or wish to contribute to the Linux source code.
Because most of the common commands and tools are open source, lots of this source code is readily available online.
In this tutorial, we’ll see how to find, read, and understand the source code of shell commands from different resources.
2. Find the Source Code
There are a few different ways to find the source code. First, we should identify the command and find it in a suitable reference. The main requirement is that the distro or command-line tool is open source.
2.1. Identify the Command
To get started, we need to work out the type of the command. It might be a shell command, built-in, alias, executable file, etc. We can get information about it, using commands such as type, which, help, man, and info.
The type command indicates if the command is alias, keyword, function, builtin, disk file, and not found. For example, it might show there are two instances of the echo command available:
$ type -a echo echo is a shell builtin echo is /usr/bin/echo
The which command prints the full path of the shell commands, helping us to find out where it is on our file system. It searches through the directories listed in the environment variable PATH. We’ll need the output of the which command, the command path, to download the source code using package managers.
$ which echo /usr/bin/echo
The help command shows a brief summary of built-in commands.
$ help help help: help [-dms] [pattern ...] Display information about builtin commands. ... $ help echo echo: echo [-neE] [arg ...] Write arguments to the standard output. ...
To see the system reference manual, we can use the man command. This provides more information than the help command:
$ man echo ...
If we wish to read the documentation in the Info format, we can use the info command.
$ info '(echo)' ...
2.2. Find the Origin
After finding out the type of the command, the next step is to find its origin. In most cases, we can find the web address in the manual.
Let’s take the example of finding the origin of xdotool command. First, we need to take a look at its manual:
$ man xdotool
Then by scrolling down the manual page, we can see the project’s website and useful references at the end of the page:
SEE ALSO xprop(1), xwininfo(1), Project site: <http://www.semicomplete.com/projects/xdotool> Source code and Issues: <https://github.com/jordansissel/xdotool> EWMH specification: <http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html>
Where the project’s site is not in the documentation, Googling for the name of the tool might also help us to find its origin.
3. Use the Package Manager
We can use package managers to get information about installed commands. This can include the source code of the commands. The first step is to find out which package those commands are in. Later we may be able to download their sources using the package manager.
Because Linux distros might make their own changes, using the package manager is the best way to find and download the source code of the installed tools.
Let’s take a look at Debian-based and Red Hat-based systems, two of the more popular distros.
3.1. Debian-Based Systems
On Debian-based systems, we can use dpkg -S <command path> to find the package name:
$ dpkg -S /bin/echo coreutils: /bin/echo
Then we use apt-get source <package name> to download the source code to the current directory:
$ apt-get source coreutils Reading package lists... Done Need to get 5,401 kB of source archives. Get:1 <a href="http://archive.ubuntu.com/ubuntu" target="_blank" rel="noopener noreferrer" data-saferedirecturl="https://www.google.com/url?q=http://archive.ubuntu.com/ubuntu&source=gmail&ust=1602420084996000&usg=AFQjCNEvfOswG2s3CI6iAIvG6HBAxTvwmQ">http://archive.ubuntu.com/ubuntu</a> focal/main coreutils 8.30-3ubuntu2 (dsc) [2,048 B] Get:2 <a href="http://archive.ubuntu.com/ubuntu" target="_blank" rel="noopener noreferrer" data-saferedirecturl="https://www.google.com/url?q=http://archive.ubuntu.com/ubuntu&source=gmail&ust=1602420084996000&usg=AFQjCNEvfOswG2s3CI6iAIvG6HBAxTvwmQ">http://archive.ubuntu.com/ubuntu</a> focal/main coreutils 8.30-3ubuntu2 (tar) [5,360 kB] Get:3 <a href="http://archive.ubuntu.com/ubuntu" target="_blank" rel="noopener noreferrer" data-saferedirecturl="https://www.google.com/url?q=http://archive.ubuntu.com/ubuntu&source=gmail&ust=1602420084996000&usg=AFQjCNEvfOswG2s3CI6iAIvG6HBAxTvwmQ">http://archive.ubuntu.com/ubuntu</a> focal/main coreutils 8.30-3ubuntu2 (diff) [39.6 kB] Fetched 5,401 kB in 25s (212 kB/s)..
The apt-get source command searches in the sources.list. This might be empty at first, so we might get some errors the first time:
$ apt-get source coreutils Reading package lists... Done E: You must put some 'deb-src' URIs in your sources.list
To solve this problem, we need to add some URIs. For example, in Ubuntu 20.04 LTS, we need to check the source code box in the software & update settings:
apt-get downloads sources and puts them in the current directory:
$ ls coreutils_8.30-3ubuntu2.debian.tar.xz Desktop Music snap coreutils_8.30-3ubuntu2.dsc Documents Pictures Templates coreutils_8.30.orig.tar.xz Downloads Public Videos
If we’re not sure about the package name to use, the Debian website provides a list of packages.
3.2. Red Hat-Based Systems
On Red Hat-based systems, we can use rpm -qf <command path> to find the package name:
$ rpm -qf /usr/bin/echo coreutils-single-8.32-4.fc32.1.x86_64
Then we use dnf download –source <package name> to download it.
$ dnf download --source coreutils-single-8.32-4.fc32.1.x86_64 enabling fedora-modular-source repository ... Last metadata expiration check: 0:05:21 ago on Sun 11 Oct 2020 12:36:12 PM +0330 coreutils-8.32-4.fc32.1.src.rpm 10 kB/s | 5.4 MB 08:47
For commands or packages that aren’t installed, we can use the repoquery command instead. Then we can use the above command:
$ dnf repoquery -q clang clang-0:10.0.0-1.fc32.i686 clang-0:10.0.0-1.fc32.x86_64 clang-0:10.0.1-2.fc32.i686 clang-0:10.0.1-2.fc32.x86_64
We do not have to provide the full package name to the dnf download –source command. It works out the most likely source for us from the command path or name and downloads the latest version of the best match:
For packages that are installed, we use the dnf download –source <command path>:
$ dnf download --source /usr/sbin/fdisk enabling fedora-modular-source repository ..... util-linux-2.35.2-1.fc32.src.rpm
For packages that aren’t installed, we use the dnf download –source <command name>:
$ dnf download --source clang enabling fedora-modular-source repository ... clang-10.0.1-2.fc32.src.rpm
We should note that this method may not be completely accurate if there is more than one package containing the command we’re interested in.
Finally, we can see the downloaded packages in the current directory:
$ ls Music Pictures clang-10.0.1-2.fc32.src.rpm Public coreutils-8.32-4.fc32.1.src.rpm Templates Desktop Documents util-linux-2.35.2-1.fc32.src.rpm Downloads Videos
4. Online References
If we wish to browse Linux source code on the web, there are a few major starting points. Because many Linux tools originated at the GNU project, GNU is a great place to start.
4.1. The GNU Software Website
Since most Linux distros use GNU packages, a useful online reference is the GNU software site. In the sub-categories, Coreutils contains shell commands and many basic tools that are mostly written in the C programming language. Therefore, we can browse the source code through cgit, gitweb, and GitHub.
4.2. Alternative Resources
5. Getting Started with Linux Sources
After we find the source code, we need programming knowledge to understand it.
A great educational resource is available in the Decoded GNU Coreutils. Here we’ll find diagrams and step-by-step guides that help the novice programmer to learn the code easily. For example, there’s lots of information about echo in its overview. In each section, the source code to their GitHub repository is also linked.
In this article, we have reviewed different methods and resources to find and read the source code of Linux commands.
First, we saw how to find the source code using links from man pages and help from the package manager. Then we looked at where to look to find common command sources.
Finally, we discussed how to get started learning about the implementation of the commands.