CS 361 Development Basics

In CS 361 (and some later courses), project development involves a lot of work on the Linux command line (also called the shell). Furthermore, all of our projects are written in the C programming language. This document is intended as a quick primer to working on the command line, as well as writing and compiling C code on stu.cs.jmu.edu (or stu for short).

Notation: The examples below illustrate what to type on a command line. It is a common convention to begin lines with $ to indicate the command prompt. Lines that do not begin with $ show the expected output from executing the command. Thus, you do not type the $ or anything on a line without a $ at the beginning.


Common shell commands

In order to compile your projects on stu, you need to know some basics of how to work on the Linux command-line.

Command Description Example
cd Changes directories. You can either use an absolute path (e.g., cd /usr/bin) or a relative path (e.g., cd bin). $ cd cs361-p1/tests
ls List files. If you want to see details (such as file size), you can do ls -l. If you are looking for files that match a particular pattern, you can use * as a wild card. $ ls -ltr *.c
...
pwd Prints the current directory. This is a good utility if you're not sure what directory you're in. $ pwd
/cs/home/stu/lennonjw
which Perform a PATH lookup for an executable program or shell built-in. This is a good way to determine if you are running the correct program. $ which ls
/bin/ls
mkdir Create a new subdirectory. $ mkdir cs361-p1/src/printer
cat Print out the contents of a file. $ cat tests/Makefile
mv Rename a file or move it to another directory. $ mv src/main.c src/project.c
rm Delete (remove) a file. If you want to delete a directory, you need to use rmdir (if the directory is empty) or rm -rf (if it is not) Warning: There is no undo. Once you delete it, it is gone. $ rm -rf build
make The command we will be using to compile code. This command assumes there is a file called Makefile in the current directory. More on this later. $ make verbose.test
gcc The actual command to invoke the GNU C compiler. If your code is C++, you should use g++ instead. (The two work more or less identically.) $ gcc -c input.c -o input.o
tar Create or extract the contents of a tar archive. Use the -c flag to create one or the -x flag to extract. You can also use -t to list a table of contents. $ tar cvfz cs361-p1.tgz cs361-p1
gzip A compression program. Tar files are generally compressed with gzip. Use gunzip to de-compress it. There is a similar pair of programs (bzip2 and bunzip2) that give you better compression (i.e., a smaller file), but they take significantly longer to run. $ gunzip cs361-p1.tgz
man Displays the help manual for a command. Press q to quit, spacebar to move to the next page, or h for help (explains more options). $ man gzip
git Command for all Git revision control operations. You will use this to submit your code. $ git add .
hg Command for all Mercurial operations. You will use to submit your code. $ hg help
$ hg add
hexdump Print the contents of a file in hexadecimal format. Very useful for working with binary files. $ hexdump add.o
0000000: 01 00 00 01 10 00 02 00
grep Great tool for pattern matching. Finds locations of text in a file. $ grep stdi file.c
#include <stdio.h>
tee Writes output to both a file and the screen concurrently. $ echo hello | tee output.txt
hello
env List current environment variables or run command with custom environment. The -i flag clears all environment variables except for those passed. $ env -i PATH= ls
env: ls: No such file or directory
echo Prints out a message to the screen. This is particularly good for working with variables. One really important environment variable is $?, which is the return code of the previous command. $ ls asldkfj
ls: asldkfj: No such file or directory
$ echo $?
1
export Add a new environment variable key-value pair. Variables are accessed with a dollar sign before the name, possibly with curly braces (e.g., $DEBUG or ${DEBUG}). Environment variables can be accessed by processes running C programs with the getenv() function (e.g., char *debug = getenv ("DEBUG");). If you set a variable without export (e.g., just do DEBUG=true at the prompt), the variable can be accessed by the shell (echo $DEBUG), but it is not passed as an environment variable to processes. $ export DEBUG=true
$ echo $DEBUG
true
$ n=42
$ echo $n
42
unset Clears an environment variable that has been exported. $ unset DEBUG
cut Splits STDIN text based on a delimeter (-d). You can select a particular field number (-f), as if the split string is an array (indexed from 1 instead of 0). $ echo "a/b/c" | cut -d'/' -f2
b
awk A full and complicated programming language, but there is one very helpful trick: print selected columns from whitespace-separated text. Use $1 to refer to the first column, $2 for the second, etc. $NF gets the last column. $ echo a b c | awk '{print $1" "$NF}'
a c

In addition, the following pieces of information are helpful:

  • $HOME or ~ refer to your home directory

    When you first pull up a terminal or ssh to a machine (such as stu, you are placed on your $HOME directory, which is for your account. So $HOME/cs361-p1 and ~/cs361-p1 both mean the same thing: they are referring to the cs361-p1 subdirectory of your account.
  • Current directory is . and parent is ..

    If you want to refer to a file (or directory) relative to your current working directory (i.e., the place you used cd to get to), you can use ./that_file. The .. refers to the directory up one level. For example:
$ ./build/program    [run "program" found in the build subdirectory]
$ cd build
$ ./program          ["program" is now in the current directory]
$ pwd
/cs/home/stu/lennonjw/p1/cs361-p1/build
$ cd ../..           [go up two directory levels]
$ pwd
/cs/home/stu/lennonjw/p1
  • Hit tab for automcomplete.

    This will save you time when typing. It also serves as an error check. If you make a typo and hit tab, you'll hear a beeping noise. This either means (a) there are multiple file names that match or (b) no file name matches. To tell which it is, hit tab again. If there are multiple files, you'll see a list of the possibilities. Otherwise, you'll see nothing.This is a good way to make sure you don't misspell directory names.
  • Learn a command-line text editor.

    There are text editors listed below that are nice to use for your personal computer. You can't use any of them on stu. As such, there really is no replacement for learning vim or emacs.
  • Use -h or --help as a first resort

    Every command has built-in documentation that you can get to by passing these flags. (Some don't have the --help option.) If you're not sure what a command does, you should go with this option first. This is how you avoid getting told to RTFM (apologies for the vulgarity and I will never tell you this, but it's common Internet slang that you may encounter).
  • Use pipes (|) to string commands together

    The pipe will taken everything that one command prints to stdout and redirect it as input to the next command's stdin. You won't see the first command's output unless the second one repeats it. These can be chained together as much as you want:
$ find . | grep \.c$ | sort
src/cmdline/parse.c
src/main/main.c
src/y86/elf.c
  • Learn pattern matching and regular expressions.

    The star (*) can be used as a wild-card when listing files. For instance, ls src/*/*.c will match all three of the .c files above. Commands like grep use special patterns called regular expressions. As a quick intro, $ means "end of the line of text," ^ means "beginning of the line," and . means "match any character." You can use \ to escape any of these special meanings.

Learning the Linux command line takes a lot of time and practice. If you want more information, you should search for something like "Linux command line tutorial." You'll find plenty of resources online.


Remote command-line access

To do anything on stu, you first need to actually connect to the machine. This is done using SSH. A popular GUI-based program for using SSH is PuTTY. Or, if you have a local command line, you can just use the following command:

$ ssh yourusername@stu.cs.jmu.edu

While you're at it, if you want to make your life easier, you can set up your system to login to stu automatically without having to enter your password. See this tutorial to learn how.


Text files on stu

Lastly, you may often want to see the contents of your files while on stu. If you just want to print out the whole thing, you can execute:

$ cat src/main/main.c
#include <stdio.h>              /* standard I/O */

#include "../cmdline/parse.h"   /* command line parser */
#include "../y86/elf.h"         /* Mini-ELF format */

int
main (int argc, char **argv)
{
  printf ("Congratulations, you have compiled your source code!\n");
  return 0;
}

If you want to edit the file, you need a text editor. Using vim or emacs is preferred. A simple approach would be to use nano:

$ nano src/main/main.c

The bottom of the screen shows you the commands for nano For instance, to exit, you hit ^x (Ctrl-x). The option for saving is called WriteOut.


Environment configuration

In your account on stu, there is a file called $HOME/.bashrc (note that the name starts with a dot "."). You can use this to create various command-line shortcuts that will make your life easier. One of them is to create an environment variable that stores common strings that you'll get very sick and tired of typing. (Note that $HOME is an environment variable that is set by default.)

Open your $HOME/.bashrc in a text editor, then go to the bottom of the file. You can then add a line to refer to a common course location. For instance, if you are in my CS 361 in Spring 2024, you might add the following line:

export CS361=/cs/students/cs361/f24/kirkpams

After you save the file, log out from stu and log back in again. You'll then be able to use a new $CS361 environment variable in commands you type. For instance, to navigate to the course's source code directory, you can type the following:

$ cd $CS361/src

Local command-line access

To get better at working with the Linux command line, you may consider setting up your Windows or Mac machine to give you a similar environment. On Windows, you can use Cygwin, which gives you a Linux-like command line for Windows, including standard Linux tools (including command-line programs you can use to compile C/C++ code). You can also use MinGW, which provides a very minimal setup that will let you compile and run code. If you have a Mac, you already have a command line. Go to Applications -> Utilities -> Terminal to bring up the terminal command line. For a full Linux-like experience, you can install MacPorts or Homebrew (recommended).


Text editors

To write code, you just need a program that can edit plain text files. You definitely should not, under any circumstances, use any WYSIWYG program, such as Word, Notepad, or Pages (Mac). These programs add formatting information to the file, and that formatting information gets treated by the compiler as if it were part of your code. The following are good (and free!) text editors that are commonly used by programmers:

Note that Eclipse is a full-featured integrated development environment (IDE), and is much more complex than any of the others. Lastly, if you are on the command line, you can use vim, emacs, or nano to edit a file, but all of those require learning special command keys. Google the name of the program to find many, many tutorials on each.


File transfers

Perhaps the easiest way to get started with C development for this class is to write your code on your own machine (e.g., a laptop), then transfer your files over manually. There are many techniques for doing this. For a GUI-based approach, you might consider installing and using one of these programs:

Alternatively, if you have a local command line (see next section), you can use scp to copy files over to stu.


Extract archive contents

When you use tar to extract (x) from a gzipped (z) file (f) in verbose format (v), you'll see a list of the files as they are extracted:

$ tar xvfz cs361-p1.tgz
cs361-p1/
cs361-p1/.hgignore
cs361-p1/Make.config
cs361-p1/Make.src
...

Compile base source code

Assuming you just extracted the code as shown above, you can compile the code using the make utility. Note that make is not a compiler. Rather, it is a project management utility that can be used to automate compilation and other tasks. This is a common tool used in the CS community and you should become familiar with it as soon as possible. When you run make from the command line, it looks for a file called Makefile. This file tells the utility what to do. You should consult the video lectures for an overview of how Makefiles work. In this case, running make with no arguments causes the following compilation steps:

$ cd cs361-p1
$ make
mkdir -p build/src/cmdline
mkdir -p build/src/main
mkdir -p build/src/y86
mkdir -p build/tests
mkdir -p build/tests/check
cp Makefile.build build/Makefile
cd build && make all
gcc  -g -O0 -Wall -Werror -c ../src/main/main.c -o src/main/main.o
gcc  -g -O0 -Wall -Werror -c ../src/cmdline/parse.c -o src/cmdline/parse.o
gcc  -g -O0 -Wall -Werror -c ../src/y86/elf.c -o src/y86/elf.o
gcc  -o ydi src/main/main.o src/cmdline/parse.o src/y86/elf.o

At this point, you can now run the compiled program:

$ ./build/ydi
Congratulations, you have compiled your source code!

False warnings from make

You may occasionally see warnings like the following. This often arises when you are working on a virtual machine system, which is what stu is. In most cases (especially in this class), this is not a problem and you can ignore the warnings.

make: Warning: File `hexdumper' has modification time 1.6e+02 s in the future
make: warning:  Clock skew detected.  Your build may be incomplete.


James Madison University logo


© 2011-2024 Michael S. Kirkpatrick.
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.