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:
fopen
– opens a filefgets
– gets a string from a filefclose
– closes a file when you are done with it
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:
- Loop through each command line argument
- Each argument is a file, so open it
- If opening the file was successful, read its contents line by line
- Print each of the lines to the terminal
- Close the file
- 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:
- Implement a basic cat command that can display the contents of a single file.
To receive 90% credit:
- Complete all previous requirements
- Implement multi-file support (including the
-
special file). - If no file is passed in, read from
stdin
.
To receive 100% credit:
- Complete all previous requirements
- Use the
getopt
library for handling command line arguments - Help (
-h
) - Line numbering (
-n
)
To receive 105% credit:
- Complete all previous requirements
- Implement meow mode (
-m
)
To receive 110% credit:
- Complete all previous requirements
- Implement word wrapping (
-w
)