The Linux programming environment

This chapter will introduce you to Linux, a Unix-like operating system called Linux. Most people run Unix with a command-line interface provided by a shell. Each line typed to the shell tells it what program to run (the first word in the line) and what arguments to give it (remaining words). The interpretation of the arguments is up to the program.

The shell

The examples in this course assume you have bash, the Bourne-again shell written by the GNU project. Other shells behave similarly for basic commands.

The Unix filesystem

Most of what one does with Unix programs is manipulate the filesystem. Unix files are unstructured blobs of data whose names are given by paths consisting of a sequence of directory names separated by slashes: for example /home/accts/some-user/cs223/hw1.c. At any time you are in a current working directory (type pwd to find out what it is and cd new-directory to change it). You can specify a file below the current working directory by giving just the last part of the pathname. The special directory names . and .. can also be used to refer to the current directory and its parent. So /home/accts/some-user/cs223/hw1.c is just hw1.c or ./hw1.c if your current working directory is /home/accts/some-user/cs223, cs223/hw1.c if your current working directory is /home/accts/some-user, and ../cs223/hw1.c if your current working directory is /home/accts/codeahoy-user/downloads.

Unix command-line programs

Here are some handy Unix commands:


man program will show you the on-line documentation (the man page) for a program (e.g., try man man or man ls). Handy if you want to know what a program does. O

You can also use man function to see documentation for standard library functions. The command man -k string will search for man pages whose titles contain string.

Sometimes there is more than one man page with the same name. In this case man -k will distingiush them by different manual section numbers, e.g., printf (1) (a shell command) vs. printf (3) (a library routine). To get a man page from a specific section, use man section name, e.g. man 3 printf.


ls lists all the files in the current directory. Some useful variants:

  • ls /some/other/dir; list files in that directory instead.
  • ls -l; long output format showing modification dates and owners.

mkdir dir will create a new directory in the current directory named dir.


rmdir dir deletes a directory. It only works on directories that contain no files.


cd dir changes the current working directory. With no arguments, cd changes back to your home directory.


pwd (“print working directory”) shows what your current directory is.


mv old-name new-name changes the name of a file. You can also use this to move files between directories.


cp old-name new-name makes a copy of a file.


rm file deletes a file. Deleted files cannot be recovered. Use this command carefully.


chmod changes the permissions on a file or directory. See the man page for the full details of how this works. Here are some common chmod’s:

  • chmod 644 file; owner can read or write the file, others can only read it.
  • chmod 600 file; owner can read or write the file, others can’t do anything with it.
  • chmod 755 file; owner can read, write, or execute the file, others can read or execute it. This is typically used for programs or for directories (where the execute bit has the special meaning of letting somebody find files in the directory).
  • chmod 700 file; owner can read, write, or execute the file, others can’t do anything with it.

Stopping and interrupting programs

Sometimes you may have a running program that won’t die.

There are various control-key combinations you can type at a terminal window to interrupt or stop a running program.


Interrupt the process. Many processes (including any program you write unless you trap SIGINT using the sigaction system call) will die instantly when you do this. Some won’t.


Suspend the process. This will leave a stopped process lying around. Type jobs to list all your stopped processes, fg to restart the last process (or fg %1 to start process %1 etc.), bg to keep running the stopped process in the background, kill %1 to attempt to end process %1 politely, kill -KILL %1 to end process %1 even if it is intercepting normal kills.


Send end-of-file to the process. Useful if you are typing test input to a process that expects to get EOF eventually or writing programs using cat > program.c (not really recommended). For test input, you are often better putting it into a file and using input redirection (./program < test-input-file); this way you can redo the test after you fix the bugs it reveals.


Quit the process. Sends a SIGQUIT, which asks a process to quit and dump core. Mostly useful if ctrl-C and ctrl-Z don’t work.

If you have a runaway process that you can’t get rid of otherwise, you can use ps g to get a list of all your processes and their process ids. The kill command can then be used on the offending process, e.g. kill -KILL 6666 if your evil process has process id 6666. Sometimes the killall command can simplify this procedure, e.g. killall -KILL evil halts all process with command name evil.

Running your own programs

If you compile your own program, you will need to prefix it with ./ on the command line to tell the shell that you want to run a program in the current directory (called ‘.’) instead of one of the standard system directories. So for example, if I’ve just built a program called count, I can run it by typing

$ ./count

Here the “$ ” is standing in for whatever your prompt looks like; you should not type it.

Any words after the program name (separated by whitespace—spaces and/or tabs) are passed in as arguments to the program. Sometimes you may wish to pass more than one word as a single argument. You can do so by wrapping the argument in single quotes, as in

$ ./count 'this is the first argument' 'this is the second argument'

Redirecting input and output

Some programs take input from standard input (typically the terminal). If you are doing a lot of testing, you will quickly become tired of typing test input at your program. You can tell the shell to redirect standard input from a file by putting the file name after a < symbol, like this:

$ ./count < huge-input-file

A ‘>’ symbol is used to redirect standard output, in case you don’t want to read it as it flies by on your screen:

$ ./count < huge-input-file > huger-output-file

A useful file for both input and output is the special file /dev/null. As input, it looks like an empty file. As output, it eats any characters sent to it:

$ ./sensory-deprivation-experiment < /dev/null > /dev/null

You can also pipe programs together, connecting the output of one to the input of the next. Good programs to put at the end of a pipe are head (eats all but the first ten lines), tail (eats all but the last ten lines), more (lets you page through the output by hitting the space bar, and tee (shows you the output but also saves a copy to a file). A typical command might be something like ./spew | more or ./slow-but-boring | tee boring-output. Pipes can consist of a long train of programs, each of which processes the output of the previous one and supplies the input to the next. A typical case might be:

$ ./do-many-experiments | sort | uniq -c | sort -nr

which, if ./do-many-experiments gives the output of one experiment on each line, produces a list of distinct experimental outputs sorted by decreasing frequency. Pipes like this can often substitute for hours of real programming.

Text editors

To write your programs, you will need to use a text editor, preferably one that knows enough about C to provide tools like automatic indentation and syntax highlighting. There are two reasonable text editors: emacs, and vim (see: vim faqs)(which can also be run as vi). Emacs and Vi have been the two contenders for the One True Editor since the 1970s—if you learn one (or both) you will be able to use the resulting skills everywhere. My personal preference is to use Vi, but Emacs has the advantage of using the same editing commands as the shell and gdb command-line interfaces.

If you are not editing directly from the terminal, you have more options. Some other popular text editors that work well with C are VS Code, Atom, and Sublime Text. The main downside to these editors is that they are relatively new, and so they don’t necessarily show up everywhere the way Emacs or Vi will. The other downside is that their relative novelty means that they won’t necessarily have the same longevity as your grandfather’s text editor: by the time you read this, there is a reasonably good chance that one or more of these popular editors is no longer very popular. But you should feel free to use whatever you are comfortable with as long as it works.

Writing C programs with Emacs

To start Emacs, type emacs at the command line. If you have never used Emacs before, you should immediately type C-h t (this means hold down the Control key, type h, then type t without holding down the Control key). This will pop you into the Emacs built-in tutorial.

My favorite Emacs commands

General note: C-x means hold down Control and press x; M-x means hold down Alt (Emacs calls it “Meta”) and press x. For M-x you can also hit Esc and then x.


Get help. Everything you could possibly want to know about Emacs is available through this command. Some common versions: C-h t puts up the tutorial, C-h b lists every command available in the current mode, C-h k tells you what a particular sequence of keystrokes does, and C-h l tells you what the last 50 or so characters you typed were (handy if Emacs just garbled your file and you want to know what command to avoid in the future).

C-x u

Undo. Undoes the last change you made to the current buffer. Type it again to undo more things. A lifesaver. Note that it can only undo back to the time you first loaded the file into Emacs—if you want to be able to back out of bigger changes, use git (described below).

C-x C-s

Save. Saves changes to the current buffer out to its file on disk.

C-x C-f

Edit a different file.

C-x C-c

Quit out of Emacs. This will ask you if you want to save any buffers that have been modified. You probably want to answer yes (y) for each one, but you can answer no (n) if you changed some file inside Emacs but want to throw the changes away.


Go forward one character.


Go back one character.


Go to the next line.


Go to the previous line.


Go to the beginning of the line.


Delete the rest of the line starting with the current position. Useful Emacs idiom: C-a C-k.


“Yank.” Get back what you just deleted.


Re-indent the current line. In C mode this will indent the line according to Emacs’s notion of how C should be indented.

M-x compile

Compile a program. This will ask you if you want to save out any unsaved buffers and then run a compile command of your choice (see the section on compiling programs below). The exciting thing about M-x compile is that if your program has errors in it, you can type C-x ` to jump to the next error, or at least where gcc thinks the next error is.

Using Vi instead of Emacs

If you don’t find yourself liking Emacs very much, you might want to try Vim instead. Vim is a vastly enhanced reimplementation of the classic vi editor, which I personally find easier to use than Emacs. Type vimtutor to run the tutorial.

One annoying feature of Vim is that it is hard to figure out how to quit. If you don’t mind losing all of your changes, you can always get out by hitting the Escape key a few times and then typing ~~~\\\ :qa!\\\ ~~~

To run Vim, type vim or vim filename from the command line. Or you can use the graphical version gvim, which pops up its own window.

Vim is a modal editor, meaning that at any time you are in one of several modes (normal mode, insert mode, replace mode, operator-pending mode, etc.), and the interpretation of keystrokes depends on which mode you are in. So typing jjjj in normal mode moves the cursor down four lines, while typing jjjj in insert mode inserts the string jjjj at the current position. Most of the time you will be in either normal mode or insert mode. There is also a command mode entered by hitting : that lets you type longer commands, similar to the Unix command-line or M-x in Emacs.

My favorite Vim commands

Normal mode

Get help. (Hit Enter at the end of any command that starts with a colon.) Escape

Get out of whatever strange mode you are in and go back to normal mode. You will need to use this whenever you are done typing code and want to get back to typing commands.


Enter insert mode. You will need to do this to type anything. The command a also enters insert mode, but puts new text after the current cursor position instead of before it.


Undo. Undoes the last change you made to the current buffer. Type it again to undo more things. If you undid something by mistake, c-R (control R) will redo the last undo (and can also be repeated).


Write the current file to disk. Use :w filename to write it to filename. Use :wa to write all files that you have modified. The command ZZ does the same thing without having to hit Enter at the end.

:e filename

Edit a different file.


Quit. Vi will refuse to do this if you have unwritten files. See :wa for how to fix this, or use :q! if you want to throw away your changes and quit anyway. The shortcuts :x and :wq do a write of the current file followed by quitting.

h, j, k, l

Move the cursor left, down, up, or right. You can also use the arrow keys (in both normal mode and insert mode).


Delete the current character.


Delete to end of line.


Delete all of the current line. This is a special case of a more general d command. If you precede it with a number, you can delete multiple lines: 5dd deletes the next 5 lines. If you replace the second d with a motion command, you delete until wherever you land: d$ deletes to end of line (D is faster), dj deletes this line and the line after it, d% deletes the next matching group of parentheses/braces/brackets and whatever is between them, dG deletes to end of file—there are many possibilities. All of these save what you deleted into register "" so you can get them back with p.


Like dd, but only saves the line to register "" and doesn’t delete it. (Think copy). All the variants of dd work with yy: 5yy, y$, yj, y%, etc.


Pull whatever is in register "". (Think paste).

« and »

Outdent or indent the current line one tab stop.


Run make in the current directory. You can also give it arguments, e.g., :make myprog, :make test. Use :cn to go to the next error if you get errors.


Run a command, e.g., :! echo hello world or :! gdb myprogram. Returns to Vim when the command exits (control-C can sometimes be helpful if your command isn’t exiting when it should). This works best if you ran Vim from a shell window; it doesn’t work very well if Vim is running in its own window.

Insert mode
control-P and control-N

These are completion commands that attempt to expand a partial word to something it matches elsewhere in the buffer. So if you are a good person and have named a variable informativeVariableName instead of ivn, you can avoid having to type the entire word by typing inf if it’s the only word in your buffer that starts with `inf`.

control-O and control-I

Jump to the last cursor position before a big move / back to the place you jumped from.


Get out of insert mode!


Unlike Emacs, Vim’s default settings are not very good for editing C programs. You can fix this by creating a file called .vimrc in your home directory with the following commands:

set shiftwidth=4
set autoindent
set backup
set cindent
set hlsearch
set incsearch
set showmatch
set number
syntax on
filetype plugin on
filetype indent on


(You can download this file by clicking on the link.)

In Vim, you can type e.g. :help backup to find out what each setting does. Note that because .vimrc starts with a ., it won’t be visible to ls unless you use ls -a or ls -A.


In this chapter, we introduced you to Linux, the bash shell, important shell commands and couple of very popular text editors. In the next chapter, we’ll go through how to compile and debug C programs.

Licenses and Attributions

Speak Your Mind