In: Computer Science
Assignment 1 – Writing a Linux Utility Program
Instructions
For this programming assignment you are going to implement a simple C version of the UNIX cat program called lolcat. The cat program allows you to display the contents of one or more text files. The lolcat program will only display one file. The correct usage of your program should be to execute it on the command line with a single command line argument consisting of the name you want to display. However, your program should also respond well when it is used incorrectly.
Processing Command-Line Arguments
Unless you have done Linux programming before you probably haven’t needed to process command line arguments. A typical C program has a main function that looks like this:
int main()
{
// body of main function
}
This works just fine if your program does not take any command line arguments. If it does, as is the case with lolcat, you will need access to those arguments. You will need to write your main function like this:
int main(int argc, char *argv[])
{
// body of main function
}
The argc parameter is the number of command line arguments provided to the program including the name of the command itself. The lolcat program should have two command line arguments if it is used correctly: the name of the command and the file to display. The argv parameter is an array of C-strings, or null-terminated character arrays. This means that argv[0] is the name of the program, argv[1] is the first command line argument, argv[2] is the second command line argument, and so on.
The lolcat program should display a usage message to standard error and exit the program using exit(1) if argc is anything other than 2. Otherwise it should use the C-string contained in argv[1] as the name of the input file to open. Note that exit function requires the following preprocessor statement:
#include <stdlib.h>
Streams
The standard way to deal with files, the console, and other sources of input and output in C is by usingstreams. For historical reasons, the data type used to deal with a stream, whether or not it uses a file, is FILE *. Working with streams requires the following preprocessor statement:
#include <stdio.h>
To declare a stream variable use the FILE * data type:
FILE *stream;
To open a file use the fopen function:
stream = fopen(filename, opentype);
To read a single character from a file, use the fgetc function:
character = fgetc(stream);
To close a file use the fclose function:
fclose(stream);
To write a string to standard output use the puts function:
puts(string);
To write a string to standard error use the fputs function:
fputs(string, stream);
To write a single character to the console use the putchar function:
putchar(character);
Linux Development Tools
You should not be using Windows development tools for this class! Instead, you should use the development tools available on Linux.
Writing Your Code
If you only have access to a Linux shell, the simplest text editor available is probably nano, which can be started by typing nano at the command line. You can then write the text file, type control-o to save it, and control-x to exit the program. You can also open an existing file by typing nano <filename> at the command line (with the actual name of the file instead of <filename>.) If you want to use a text editor with more features for writing source code you can try using vim or emacs.
If you are using a Linux distribution with a graphical interface, then you can use a GUI text editor like gedit, kedit, gvim, or the GUI version of emacs, depending on what is available on your system. Ultimately it doesn’t matter what text editor you use, as long as you keep track of where you are saving your files.
Compiling Your Code
Your source file should be called yourlastnameAssign1.c except with your actual last name. To compile this code you should use the gcc compiler on the Linux server. To create an executable file called lolcat use the following command:
gcc -o lolcat yourlastnameAssign1.c
If your program compiled, you should see an entry for lolcat when you execute the ls command.
Running Your Code
Since your home directory on Linux is not in your execution path, you will need to specify the file you are executing directly by putting a ./ before the name of the executable. Here are some examples of what several runs should look like:
$ ./lolcat foo.txt
This is a text file that I created
in a text editor in order to test
out the lolcat program.
$ ./lolcat
usage: lolcat <filename>
$ ./lolcat foo.txt otherFile.txt
usage: lolcat <filename>
$ ./lolcat no_such_file.txt
error: file not found
What to Hand In
Your source file should have comments at the top listing your name, Assignment 1, and a brief explanation of what the program does. Upload the source file to D2L in the dropbox called Assignment 1.
/*****************************************************/
/************* Name: ***********/
/************* Assignment 1 ************************/
/*****************************************************/
//header files declaration
#include <stdio.h>
#include <stdlib.h>
//main function
int main(int argc, char *argv[])
{
//declare file stream
FILE *f;
//declare character variable
char c;
//check the number of arguments
if(argc!=2)
{
printf("usage: lolcat
<filename>\n");
exit(1);
}
//open a file in read-only mode
f = fopen(argv[1], "r");
//check error on opening the file
if(f==NULL)
{
fputs("error: file not found\n",
stderr);
exit(1);
}
//read a character and check EOF
while((c=fgetc(f))!=EOF)
{
//print the character to the
console
putchar(c);
}
//close a file
fclose(f);
}
Output: