Wrapping printf(1)

Working on an application that had become a little… verbose, I decided it was finally time to wrap my prints in a function that could easily be switched on or off depending on whether or not I wanted it to be verbose. One approach I had seen before (from my OS professor) that has a certain amount of merit is to wrap statements with a macro:

#ifdef DEBUG
printf(....);
#endif

The nice thing about this approach is that debugging can be turned on or off easily at compile time. However, my experience has been that it leads to a lot of typing, and seeing too many macros in the middle of code makes my brain explode in a fiery rage. So, I figured that if I wrapped my prints in another function (I called mine ‘log’ and ‘error’), I could avoid this whole mess and keep my sanity. I’ve done this with a number of other projects in other languages, but I had to learn some magic to do it in C.

Lesson Learned #1 : Variable arguments. It turns out you can define functions that take a variable number of arguments with va_list (from ). You define such a function:

void log(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
...
va_end(args);
}

Lesson Learned #2 : However, from what I can gather, you can’t just inject printf directly into this. However, having anticipated this, there is a set of functions designed for cases like this: vfprintf, vprintf, vsnprintf, vsprintf. The ‘v’ stands for va_list (variable-argument list), and you can use them just like you’d expect:

void log(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
fprintf(log_fd, "NOTE : ");
vfprintf(log_fd, fmt, args);
va_end(args);
}

The thing I like about this approach is that you have control over how log messages get printed in one place. So, for example, if I provided another function, setLogFD, then I could easily just set the file descriptor where all log messages get printed. So easy! Something I’ve used this for in other instances (especially servers) is to also inject additional information like a timestamp on every message. So, when I call:

log("Some event '%s' just happened.\n", event_name);

Then I automatically get “NOTE : ” and maybe a timestamp prefixed on that message. Which make code look clean, and adds a great deal of functionality. I actually added another function error(…) that prints to a different file descriptor in case I want to suppress debug messages, but no error messages. For additional layers of debugging, you might do something like this:

void log(int level, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
FILE* fd = my_log_files[level];
fprintf(fd, "NOTE : ");
vfprintf(fd, fmt, args);
va_end(args);
}

This way, at startup, you could easily set some of the file descriptors in my_log_files to stderr and some to point to /dev/null or otherwise dissolve into the ether.

Tagged with:
 

Like MacGy-ay-ay-ay-ver.

Scenario: you need to boil some water to incapacitate a guard (a hot cup of tea puts him right to sleep. Also, he’s very trusting when it comes to strangers offering him tea), and you’ve got sandpaper, two soda cans, a razor, a tuft of fiberglass insulation, a tack and a bottle of Heet at your disposal. Also, the internet to watch this metacafe video.

MacGyver StoveI had seen this before and in various design complexities, but I really like the compactness and ease of this one. I decided to scrounge up some Heet ($2.10 at a local gas station), a couple of cans, sandpaper and a razor blade (both on hand), and pull a little piece of insulation off of some that happened to be sitting in our basement.

It got surprisingly hot – I tried setting an oven rack over it with a kettle (to knock out that tea-loving guard), and it started to melt one of the bars of the rack. I expected it to be hot, but not hot enough to melt parts of an oven rack. Who knew?

Success: certainly.

Tagged with:
 

Ghetto Shunt

I’ve been putting together a media server for my newly-hacked XBox media center, and I had an old 120 gig hard drive laying around that wasn’t seeing much use. I thought I’d throw it in the box, giving me 240 gigs total to keep online for my viewing pleasure. The problem was, however, that I had removed the shunt at some point, and couldn’t find one around the house (who keeps these, anyway)? So, presenting my very ghetto make-shift shunt:

Ghetto ShuntMade from one of those yellow connectors (if you know the name of what I’m talking about, please let me know), I snapped off the part where you put the wire in and then clamp it with pliers. Before using that, I made sure I had the right setting (I wanted this one as the slave HD), by touching a screwdriver to the two pins associated with that setting and held it there as I booted the machine. Probably a safe/smart move (but in all reality, how much current flows through those pins, anyway?).

Tagged with:
 

XBMC

My XBox is now my gateway to my media. $4.73 for Splinter Cell (how this particular hack gets the Linux installer running), and $21.81 for an Action Replay kit to transfer the files. Now, all the media on the LAN are at the fingertips of my XBox. Music, Pictures, Movies and TV Shows – the whole gambit.

I used this Lifehacker article as a guideline. All in all, it took about an hour.

Watching Scrubs TV Shows Music
Weather / RSS Watching A Movie
Tagged with: