COMP 3400 Project 1: Gentle introduction to C programming
Spring 2017
Due February 2
Worth 50 of your 200 project points
This is an "individual with a partner" assignment

Overview

This project will introduce you to C programming. The C language was developed by Brian Kernighan and Dennis Ritchie at Bell Labs starting in the late 1960s, as an alternative for assembly language for implementing the first Unix operating system. It subsequently became the language of choice for writing operating systems, although now largely supplanted by C++ (another Bell Labs invention). It is an appropriate choice both to implement projects in this course and also to give you experience with a language other than Java. C is not object oriented but most of its syntax is nearly identical to Java. I have posted a page of selected C references on the web that includes links to a couple tutorials on "C for Java Programmers"

For this your first C program, I promised a gentle introduction. You may write your C program using jGRASP on suitably configured lab computers. This is quite a different programming environment than you would experience if using a Linux command interface. Later we'll do a second C project in that environment.

Speaking of command interfaces...for this project you will fill in details of a partially-implemented C program that provides a simple command interface. If you've used the DOS-like command window provided with Windows, you are familiar with the concept. The interface issues a prompt, you type in a command, the command is carried out, its results (if any) are displayed, and another prompt is issued. Unix/Linux command interfaces are called shells, and several are available.

Your assignment is to begin development of our very own shell, to be called osh, for Otterbein SHell. You will write it in C, and we will start with some basic features. A source code framework is provided. Details below.

The term "individual with a partner" means you may work in parallel with a lab partner at adjacent computers and help each other out, but each partner will physically produce and submit her own solution. This will help as you become familiar with the new language and tools.

Basic structure of a shell (command line interpreter)

A command line interpreter (a.k.a shell) is essentially an infinite while loop. Within the loop is a printf() call to issue the prompt, then a scanf() or fgets() call to receive the user's command, then the logic to recognize which command was entered and finally the logic, usually a switch statement, to carry out that command. The exit command is carried out simply by executing a return 0; statement to terminate the main program.

The logic to recognize a command name should use the strcmp() (string compare) function. It takes two arguments for the two strings to be compared. It returns 0 if they are equal, a negative integer if the first is less lexigraphically and a postive integer if the first is greater.

Your assignment is to extend osh.c

As stated above, osh is a command interpreter. The basic structure of the interpretor is provided for you, in file osh.c. You'll find it in the Class server's Common folder for this course, or you can download it here.

As provided, osh correctly performs the exit command. It also recognizes the files command but does not perform it.

You will extend osh to implement additional commands as described below.

Make sure you can compile and run the provided osh.c, before trying to make any changes to it.

Commands to implement

files

Will display a count of the number of files in the "current" directory. For this project, this means the directory from which you ran the program. The following C code should get this information:
  int fileCount;
  String getCount = "dir/a | find \"File(s)\"";  // For Linux use: "ls -l | wc -l"
  FILE *in = popen(getCount, "r");
  fscanf(in, "%d", &fileCount);
  pclose(in);
  // fileCount now contains the count.  You write the code to print it out.

This bit of C code uses the popen function, which carries out a DOS/Linux command then opens the command response for reading, as if it were coming from a file. The fscanf function then reads this response into the int variable fileCount. The DOS/Linux command itself is a two-command sequence stored as a string into variable getCount. The first command requests a directory listing. This is done in DOS using the dir command and in Linux using the ls command. Both are configured to produce "full" information, not just the file names. This is done in DOS with the /a (for attributes) modifier and in Linux with the -l (for long) modifier. The listing is produced with each filename on a different line. The output of the first command, the listing itself, is then piped (the vertical bar) as input into the second command to determine the count. This is done in DOS using the find command, modified with "File(s)" to get the summary line that contains the count of files. The Linux equivalent is the wc (for word count) command, modified with -l (for lines) that gets the count of lines instead of words. The final result is thus the file count (actually the Linux result includes one extra line so subtract one from the result).

You must study the structure of osh.c to understand how it recognizes and performs input commands. Then substitute your code from the files command into it. Then make it run. You need to understand this structure so you'll know how to add additional commands.

display file

Display the contents of the given file. The file is presumed to exist in the underlying directory. Use fopen to open the file, fgetc to read and echo each character (you are finished when fgetc returns EOF), and fclose when finished. Yes, just read it as a stream of characters. If the file does not exist, print the error message: display: file file does not exist (where file is the given filename)

copy [-f] file1 file2

Copy the contents of file1 into file2. The square brackets around -f indicate it is optional and are not typed. The file1 is presumed to exist in the underlying directory. Use fopen to open the files, fgetc to read (you are finished when it returns EOF), fputc to write, and fclose when finished. As above, process each file as an unstructured sequence of characters. If the first file does not exist, print the error message: copy: file file1 does not exist (where file1 is the first filename). If the second file already exists and the -f (force) option is given, overwrite the existing file. If the second file already exists and the -f option is not given, print the error message: copy: file file2 already exists (where file2 is the second filename).

Scoring

Maximum score is 50 points, broken down as follows:
Max Pts Item
  "files" command - 10 points maximum
2 Implemented as function
1 documented
5 Test case "files" produces correct result
2 Test case "files lines.txt" displays error message for too many arguments
  "display" command - 20 points maximum
2 Implemented as function
1 documented
13 Test case "display lines.txt" produces correct result (displays file contents)
4 Error test cases display error message only, and re-issue prompt
  "copy" command - 20 points maximum
2 Implemented as function
1 documented
9 Test case "copy lines.txt temp.txt" produces correct result - creates new file
2 Test case "copy -f lines.txt temp.txt" produces correct result - overwrites
2 Test case "copy -f lines.txt new.txt" produces correct result - creates new file
4 Error test cases display error message only, and re-issue prompt

To Turn In

Send me your completed osh.c file as an email attachment to psanderson@otterbein.edu.


[ COMP 3400 | Peter Sanderson | Math Sciences home page | Otterbein ]

Last updated:
Peter Sanderson (PSanderson@otterbein.edu)