OK, so in the spirit of Code-Golf, I\'m trying out something new here: Code-Bowling.
In golf, you try to get the lowest score (smallest application, mos
/*
* TODO: write manpage
*/
#include
#include
#include
#include
#include
#include
#define ERROR_MAX 2048 /* arbitrary, must account for argv[0] */
#define MSG_SIZE (5+9+1) /* +1 for newline, +1 for NUL */
#if defined(linux) || defined(BSD) && BSD > 199300L
extern char const *__progname;
# define progname __progname
#else
static char *progname;
#endif
typedef enum _Progerr {
IO_ERR = 1,
RND_ERR = 2
} progerr_t;
static const char GREET_START[5] = "Good"; /* XXX move to Makefile? */
static const char *TIMES_OF_DAY[5] = {
"Morning",
"Afternoon",
"Evening",
"Night",
NULL
};
int main()
{
char errbuf[ERROR_MAX];
char msgbuf[MSG_SIZE];
char *slash;
const char **time_of_day;
int fd, rnd;
size_t greet_len;
#ifndef progname
/* we want proper error messages */
progname = argv[0];
if ((slash = strrchr(progname, '/')) != NULL)
progname = slash+1;
#endif
/* get REAL randomness; can't trust rand(3).
* avoid stdio, it's slow. */
#ifdef DEBUG
write(STDERR_FILENO, "getting random data\n", sizeof("getting random data\n")-1);
#endif
if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
if ((fd = open("/dev/random", O_RDONLY)) == -1)
rnd = rand(); /* last resort, for MSYS etc. */
}
if (fd >= 0 && read(fd, &rnd, sizeof(int)) != sizeof(int)) {
close(fd);
goto rngerr;
}
/* higher bits of rand() have better entropy */
assert(sizeof(int) >= 4); /* should be compile-time assert */
rnd = (rnd >> 24) & 0x03;
for (time_of_day = TIMES_OF_DAY; *time_of_day && rnd; time_of_day++, rnd--)
;
if (!time_of_day)
goto rngerr;
sprintf(msgbuf, "%s %s", GREET_START, *time_of_day);
greet_len = strlen(msgbuf);
msgbuf[greet_len] = '\n';
if (write(STDOUT_FILENO, msgbuf, greet_len+1) == -1)
goto write_err;
return 0;
rngerr:
sprintf(errbuf, "%s: cannot get random data\n", progname);
write(STDERR_FILENO, errbuf, strlen(errbuf));
return (int)RND_ERR;
write_err:
sprintf(errbuf, "%s: cannot write to stdout\n", progname);
write(STDERR_FILENO, errbuf, strlen(errbuf));
return (int)IO_ERR;
}