Curiosity and the I/O Cat

In this lab, we’ll learn a bit more about I/O by building our own version of the cat Unix utility. You can learn more about cat by checking the man pages with man cat.

Thus far, we’ve only really covered output – printing to the terminal with printf or puts. To implement cat, we also need to be able to read a file and then print its contents. The functions you should use for this lab are:

You’ll want to review the man pages for each of these to understand how they work.

Check out the class schedule page for a full walkthrough of cat to get an idea of how it should work. The basic workflow is:

  1. Loop through each command line argument
  2. Each argument is a file, so open it
  3. If opening the file was successful, read its contents line by line
  4. Print each of the lines to the terminal
  5. Close the file
  6. Move on to the next file

That’s it!

When you read the files, you have to have somewhere to put their contents temporarily before printing them – a buffer. We’ll create a character array to serve as our buffer:

// Create a buffer of 128 characters
char buf[128];

// ... and then pass 'buf' to the fgets function

Testing your code

When you are done, your cat program should be able to concatenate several files. If no file is specified, or the file name is ‘-’, it should read from stdin just like cat does. Test it out with a few text files of varying sizes, and compare your output with that of the regular cat utility.

Here are some test cases to verify that everything is working properly.

[mmalensek@mmalensek-vm ~]$ ./sfcat
Type something
Type something (whatever you type gets repeated!)
[mmalensek@mmalensek-vm ~]$ echo Hello | ./sfcat
Hello
[mmalensek@mmalensek-vm ~]$ ./sfcat README.md
(contents of README.md are displayed)
[mmalensek@mmalensek-vm ~]$ echo Wow | ./sfcat README.md - sfcat.c
(contents of README.md are displayed, then "Wow", then contents of sfcat.c)

More Options

Next, add command line option parsing using getopt like you did in the last lab. You should support a help (-h) flag as well as a line numbering (-n) flag.

If -n is passed to the program, provide a line count like this:

[mmalensek@mmalensek-vm ~]$ ./sfcat -n /etc/passwd
     1	root:x:0:0::/root:/bin/bash
     2	bin:x:1:1::/:/usr/bin/nologin
     3	daemon:x:2:2::/:/usr/bin/nologin
     4	mail:x:8:12::/var/spool/mail:/usr/bin/nologin
     5	ftp:x:14:11::/srv/ftp:/usr/bin/nologin
     6	http:x:33:33::/srv/http:/usr/bin/nologin
     7	nobody:x:65534:65534:Nobody:/:/usr/bin/nologin
  ( ... the rest of the lines are omitted for brevity ...)

Check the man page for printf (man 3 printf) to find out how to right-align the line count.

Extra Feature 1: if you are already done and need an additional challenge, add an -m flag that turns on an option that adds “meow!” to the end of each line. Now that’s an exciting feature!

Extra Feature 2: you might notice that if you sfcat (or even cat) a file with long lines, they don’t wrap nicely in your terminal and can be a bit difficult to read. Add a -w (word wrap) option that will wrap lines that are longer than 80 characters. If a word would be cut off by the wrap, show it on the next line instead.

Grading and Submission

Check your code into lab3 within your lab repo. Provide a Makefile that builds the program, and also include clean and install recipes (install to /usr/local/bin).

To receive 80% credit:

To receive 90% credit:

To receive 100% credit:

To receive 105% credit:

To receive 110% credit: