1. Overview

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>

In its GitHub repository, we can see the xdotool.c file, which contains the source code.

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 to find the package name:

$ dpkg -S /bin/echo
coreutils: /bin/echo

Then we use apt-get source 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 http://archive.ubuntu.com/ubuntu focal/main coreutils 8.30-3ubuntu2 (dsc) [2,048 B]
Get:2 http://archive.ubuntu.com/ubuntu focal/main coreutils 8.30-3ubuntu2 (tar) [5,360 kB]
Get:3 http://archive.ubuntu.com/ubuntu 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:

image 2

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 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 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.

For instance, in the sub-category of GNU Coreutils in GitHub, we can read the source code of commands such as cat, df, ls, rm, and echo. 

4.2. Alternative Resources

Util-linux is a standard package, which is distributed by the Linux Kernel Organization. This is used as a part of the Linux operating system and provides some of its source code via GitHub and cgit.

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.

6. Conclusion

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.