CS 3733 Operating Systems, Spring 2000 Assignment 1

Due Friday, February 4, 2000


The purpose of this assignment is to make sure you are familiar with C programming, string manipulation using pointers, memory allocation, use of makefiles, and separate compilation.

Use the cover sheet in /usr/local/courses/cs3733/spring2000/cover1.ps as the first sheet when handing in your assignment. Make sure you include your makefile and lint output. Use separate directories for Parts 1 and 2 of this assignment so that you can keep the Part 1 source code while you are testing Part 2. Keep all source code created for this course until you have received your final grade for the course. is over.

Part 1. Safe readln
One of the majors causes of security problems on Unix systems is buffer overrun. This problem occurs when a finite size buffer is allocated for input, the input is too large for the buffer, and this condition is not tested for. It can cause parts of the program to be overwritten, sometimes allowing a malicious user to execute arbitrary code.

Write a function:
char *readln(int fd)
which takes an open file descriptor as a parameter and reads in a line from that file descriptor. It returns the line read as a string which will normally have the newline as the last character. If an end-of-file is reached before any characters have been read, or if a memory allocation error occurs, a NULL is returned. Otherwise, if an end-of-file is reached the string returned will not have a newline as the last character.

The readln function allocates space needed for the string. You may not make any assumptions about the length of the line. One solution is to malloc a certain amount of space and do a larger malloc if the original one was too small. The initial buffer size should be a symbolic constant. Test your program will small values of the buffer size to make sure it is working correctly. Your functions should not have any memory leaks.

Write a main function (in a separate file called testread.c) to test your readln. The main program will call readln repeatedly for standard input until a NULL is returned, and output the results to standard output. The main program should free the space generated by readln. The main program should also identify the programmer with a line sent to standard error. All other output should go to standard output. Test your program by redirecting the input to come from a file and redirecting the output to go to a file. Use diff to check that the input and output are identical.

Part 2.
Part 1 assumes that there are no 0 bytes in the input stream. Modify your readln so that it ignores zero bytes in the input stream. Add static variables to your readln file to keep track of the number of lines read, the length of the longest line read, the maximum number of memory allocations needed to process a line, and the size of the largest input buffer used. The length of the line should include the newline at the end. Add functions to this file to return these values and the initial buffer size. Modify your main program so that it reports to standard error these values with descriptive phrases. For example, running the main program should produce output like the following:

   testread < infile > outfile
   This program was written by Steven Robbins
   Initial buffer size: 10, largest buffer size: 160
   Maximum number of mallocs: 5
   Number of lines: 58, longest line: 80
Test your program with the infile available in /usr/local/courses/cs3733/spring2000/infile and hand in the output generated. Run diff on the infile and outfile to show that they are identical.