I'm trying to get my head around C-string processing. I've decided to try my hand at making a dirt-simple magnet link generator. The format that a magnet link needs is
magnet:?xt=<hash>&tr=tracker1url&tr=tracker2url&....&tr=trackerNurl
This program takes a hash as an argument on the command line, and takes lines on standard input which are either empty lines or the URLs of trackers.
Am I doing this in a sane way? What can I do better? Please note that I'm fairly new to C, so if you see anything weird or dangerous, let me know about that as well.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 4096
/*
* Exit with the given code, and print an error
* message if ec != 0
*/
void die(int ec, char *message) {
if (ec) {
fprintf(stderr, "ERROR: %s\n", message);
}
exit(ec);
}
/*
* takes one input argument -- the hash code
* of the thing you're looking to generate a
* magnet link for, on the command line, and
* then a list of trackers on the stdin stream.
*/
int main(int argc, char **argv) {
// If there is no
if (argc < 2)
die(1, "No hash code given!");
// buf is the internal buffer. bufEnd is supposed
// to be a pointer to the very end of the string
// to prevent linear time string concatenation.
char buf[SIZE];
char *bufEnd;
// line is a buffer for each line of standard in
char line[SIZE];
// 20 is the number of chars in "magnet:?xt=..."
// magic number is bad but i don't know a better way
if (20 + strlen(argv[1]) >= SIZE)
die(1, "buffer overflow detected");
// Here we initialize buffer
bufEnd = buf + snprintf(buf, SIZE, "magnet:?xt=urn:btih:%s", argv[1]);
// keep reading input lines, adding "&tr=..." params
// to the magnet link for non-empty lines
while (fgets(line, SIZE, stdin)) {
int len = strlen(line); // find out how big this line is
// check for empty line. skip it if it's empty
if (!(strcmp(line, "\n"))) continue;
// check to see if there's room left in the array
// and if so, then add the next arg.
if (SIZE - (bufEnd - buf + len + 4) > 0) {
bufEnd += sprintf(bufEnd, "&tr=%s", line) - 1;
}
else die(1, "buffer overflow detected");
}
// change the trailing newline into a nul byte
if (bufEnd - buf < SIZE) {
*bufEnd = '\0';
}
else die(2, "crazy buffer overflow detected");
// output it with backwards brackets (to show whitespace...
// debugging purposes)
fprintf(stdout, ">%s<\n", buf);
fflush(stdout);
return EXIT_SUCCESS;
}