Listing 1:  holidays.conf 

# Input file for /usr/local/bin/holidays, which runs in the wee hours of
# the morning of Jan. 1st, and generates /etc/holidays for the new year.
#
# New Year`s Day is Jan. 1st, unless it falls on a weekend
1       1       1-5     New Year's Day
1       2       1       New Year's Day
# Memorial Day is the last Monday in May
5       25-31   1       Memorial Day
# Independence Day is July 4th, unless it falls on a weekend
7       4       1-5     Independence Day
7       5       1       Independence Day
7       3       5       Independence Day
# Labor Day is the first Monday in September
9       1-7     1       Labor Day
# Election Day is the Tuesday after the first Monday in November
#11     2-8     2       Election Day
# Thanksgiving is the fourth Thurday in November
11      21-28   4       Thanksgiving Day
11      22-29   5       day after Thanksgiving
# Christmas Eve is December 24th, unless it falls on a weekend
12      23      4-5     Christmas Eve
12      24      1-5     Christmas Eve
 Christmas is December 25th, unless it falls on a weekend
12      25      1-5     Christmas
12      26      1-2     Christmas
# New Year`s Eve, if it falls on a Friday
12      31      5       New Year`s Eve

==> holidays.c <==
#include <stdio.h>
#include <sysexits.h>
#include <time.h>

/*
 * Creates /etc/holidays file
 *
 * Usage:  holidays [-year <year>] [-prime <start> <end>]
 *
 * Input file is of the form:
 *	<month> <days-of-month> <days-of-week> <holiday name>
 * where:
 *	<month> is in the range 1 through 12
 *      <days-of-month> is in the range 1 through 31
 *      <days-of-week> is in the range 0 through 6, where 0 is Sunday 
 *      <holiday-name> is a character string extending to EOL
 *
 * Output file is the holidays file expected by the accounting system.
 *
 */

char *progname;

void
usage()
{
    static char *help_message[] = {
	"where options include:\n",
	"\t-year <year>\t\tyear for which holidays are to be calculated\n",
	"\t-prime <start> <end>\tstarting and ending times for prime time\n",
	"\n",
	"Options may be abbreviated to the shortest unambiguous prefix.\n",
	"\n",
	NULL
    }, **cpp;

    fprintf (stderr, "usage: %s [-options ...]\n\n", progname);
    for (cpp = help_message; *cpp; cpp++) {
	fputs (*cpp, stderr);
    }
    exit(EX_USAGE);
}

void
dataerr(errmsg)
char *errmsg;
{
	fprintf(stderr,"%s: %s\n",progname,errmsg);
	exit(EX_DATAERR);
}

main(argc,argv)
int argc;
char **argv;
{
    int i,j,n,mday_start,mday_end,wday_start,wday_end;
    long t;
    char buffer[1024],mdays[93],wdays[14];
    char *name, *prime, *non_prime;
    struct tm date, *u;

    progname = argv[0];

    /* default to current year; except in December, when we assume next year */
    t = time(NULL);
    memcpy(&date,gmtime(&t),sizeof date);
    if (date.tm_mon == 11) date.tm_year += 1;

    /* prime time defaults to 8:00 AM to 5:00 PM */
    prime = "0800";
    non_prime = "1700";

    /* process arguments */
    for (i=1;i<argc;i++) {
	char *arg = argv[i];
	if (arg[0] == '-') {	/* process command line switches */
	    switch (arg[1]) {
	      case 'y':		/* -year <year> */
		if (++i >= argc) usage();
		date.tm_year = atoi(argv[i]);
		if (date.tm_year >= 1000) date.tm_year -= 1900;
		if (date.tm_year <= 0) usage();
		continue;
	      case 'p':		/* -prime <start> <end> */
		if (i+2 >= argc) usage();
		prime = argv[++i];
		non_prime = argv[++i];
		continue;
	      default:
		usage();
		/* NOTREACHED */
	    }
	} else {
	    usage();
	    /* NOTREACHED */
	}
    }				/* end argv for-loop */

    fputs("*\n* Curr\tPrime\tNon-Prime\n* Year\tStart\tStart\n*\n",stdout);
    fprintf(stdout,"  %4d  %s    %s\n",1900+date.tm_year,prime,non_prime);
    fputs("*\n* Day of\tCalendar\tCompany\n* Year\t\tDate\t\tHoliday\n*\n",
		stdout);

    while ( 1 ) {
	fgets(buffer,sizeof buffer,stdin);
	if (feof(stdin)) break;
	if (buffer[0] == '#') continue;	/* comment to ignore */
	if (buffer[0] == '*') {		/* comment to pass along */
	    fputs(buffer,stdout);
	    continue;
	}
	n = sscanf(buffer,"%d %92s %13s %n",&date.tm_mon,mdays,wdays,&i);
	if (n != 3) dataerr("data error in input file");
	if ((date.tm_mon < 1) || (date.tm_mon > 12)) exit (1);
	date.tm_mon -= 1;
	name = &buffer[i];
	n = sscanf(mdays,"%d-%d",&mday_start,&mday_end);
	if (n == 0) dataerr("bad days-of-month field in input file");
	if (n == 1) mday_end = mday_start;
	n = sscanf(wdays,"%d-%d",&wday_start,&wday_end);
	if (n == 0) dataerr("bad days-of-week field in input file");
	if (n == 1) wday_end = wday_start;
	for (date.tm_mday=mday_start;date.tm_mday<=mday_end;date.tm_mday++) {
	    t = timegm(&date);
	    u = gmtime(&t);
	    if ((u->tm_wday >= wday_start) && (u->tm_wday <= wday_end)) {
		char prefix[20];
		strftime(prefix,sizeof prefix,"%j\t\t%b %d",u);
		printf("  %s\t\t%s",prefix,name);
	    }
	}
    }
    exit(EX_OK);
}

