todo.c

Todo is a simple program for managing a todo file.
I keep mine at ~/.todo
Each line is a different task to do, if todo is called without any
args, then it displays the todo file.
Todo accepts the flags -s, -a, and -d for show, add, and delete
respectively. Only -d takes an argument for the line number to
remove.
Writing todo was relatively simple. Showing the todo is trivial,
open the file for reading, write each character to stdout until the
end of file.
Appending to the todo is straight forward as well, read characters
from stdin and append to the file until a newline is seen.
Deleting a line was a little trickier. I elected not to read the
file into memory and modify it there, but instead read the portions
of the todo file I wanted to keep into a temporary stream, counting
newline characters to determine which line was to be skipped.
Then the todo file is truncated and the temporary stream is rewound
and read back into the location of the original todo file.

Additional features I am considering:
       Displaying the todo file with line numbers so it is easier
       to know the right line to remove when a task is completed.
       Accept additional args for the append flag, -a, so a new
       task may be added by
               $ todo -a <new todo here>
       Let the default location of the todo file be discovered
       relative to a user's home instead of being hardcoded. Right
       now the current file location is declared in a global at
       the top of the source file.

Neat things learned:
       Adding the -H flag to the $CFLAGS displays all headers
       sourced and their paths. I like how easy it is to look
       through headers for additional information. e.g. I knew
       there was a global variable for the max size on an integer,
       but didn't know precisely where it was defined or what it
       was named. Knowing header locations on my system made it
       easy to find without needing to look online.

       There is an interesting security nuance around the system
       calls to create tmp files. mktemp, tmpnam, and tempname all
       return paths for temporary files. Typically these paths are
       then used to create, write, or read from later in the file.
       Primarily there is a race condition, between getting the
       name and reading the file, and an attacker may place a file
       at the expected location. Secondarily, tmp file locations
       and permissions are system dependent and may not be created
       securely. This information is layed out in the openbsd man
       pages tmpnam(3), mktemp(3) and related pages.
       Exploiting a race condition in my own program would be a
       fun challenge.
       I sidestepped these issues using tmpfile(3) which is based
       on mkstemp(3).