/*
 * This file belongs to FreeMiNT.  It's not in the original MiNT 1.12
 * distribution.  See the file Changes.MH for a detailed log of changes.
 */

/*
 * mkbuild.c - FreeMiNT.
 * Create build.h.
 * Author: Guido Flohr <guido@freemint.de>
 * Started: Mon, 30 Mar 1998.
 * 
 * Changed: Sun, 05 Apr 1998 (Draco)
 * - Renamed output file to "build.h".
 * 
 * Changed: Sat, 18 Apr 1998 (Guido)
 * - De-ANSIfied.
 * - Clean-up.
 * - Bugfix: BUILD_DAY_OF_WEEK is now 1 for Monday and 7 for Sunday
 *   and BUILD_MONTH is now 1 for January and 12 for December.  
 *   Strange, but that's the way Ssystem expects it.
 * 
 * Changed: Fri, 19 Nov 1999 (Guido)
 * - _build_h -> build_h.
 * - Added information about build hostname.
 * - Added ctime.
 */

# define _GNU_SOURCE

# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
# include <errno.h>
# include <signal.h>
# include <unistd.h>
# include <sys/param.h>
# include <locale.h>

# define OUTNAME "build.h"
char* killfile = NULL;

void signal_handler (int sigum);

char _host[64];
char _domain[256];

char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
		  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
char* wdays[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

#ifdef __CYGWIN__
int
getdomainname (char *buf, size_t len)
{
	strcpy (buf, "cygwin");
	return 0;
}
#endif

int
main (int argc, char* argv[])
{
	char *myname = argv [0];
	time_t then = time (NULL);
	char *host = getenv ("BUILD_HOST");
	char *domain = getenv ("BUILD_DOMAIN");
	char *user = getenv ("BUILD_USER");
	
	/* Fixme: Should we use gmtime() instead of local time? */
	struct tm *now = localtime (&then);
	FILE *out = fopen (OUTNAME, "wb");
	int catchsigs [] = { SIGHUP, SIGINT, SIGQUIT, SIGTERM, -1 };
	int i;
	
	if (host == NULL)
	{
		host = _host;
		if (gethostname (_host, sizeof _host) != 0)
		{
			perror ("gethostname");
			return 1;
		}
	}
	
	if (domain == NULL)
	{
		domain = _domain;
		if (getdomainname (_domain, sizeof _domain) != 0)
		{
			perror ("getdomainname");
			return 1;
		}
	}
	
	if (user == NULL)
		user = getlogin ();
	
	if (user == NULL)
		user = "Bill.Gates";	/* That will teach 'em to provide
					 * a sane environment.
					 */
	
	for (i = 0; catchsigs [i] > 0; i++)
		if (signal (catchsigs [i], signal_handler) != 0)
			fprintf (stderr, "%s: warning: can't catch signal #%d: %s\n",
				myname, catchsigs [i], strerror (errno));
	
	if (out == NULL)
	{
		fprintf (stderr, "%s: error: can't open `%s' for writing: %s\n",
        		myname, OUTNAME, strerror (errno));
		
		return 1;
	}
	else
	{
		killfile = OUTNAME;
	}
	
	fprintf (out,
		"/* Do not edit this file.  It is automatically created.  Edit\n"
		" * %s instead.\n"
		" */\n\n", __FILE__
	);
	
	fprintf (out,
		"# ifndef _build_h\n"
		"# define _build_h\n"
		"\n"
		"# define BUILD_DAY_OF_WEEK %d	/* Attention: Mon is 1, Sun is 7!  */\n"
		"# define BUILD_DAY %d\n"
		"# define BUILD_MONTH %d		/* Attention: range from 1 to 12!  */\n"
		"# define BUILD_YEAR %d\n"
		"# define BUILD_HOUR %d\n"
		"# define BUILD_MIN %d\n"
		"# define BUILD_SEC %d\n"
		"\n"
#ifdef __CYGWIN__
		"# define BUILD_CTIME \"%s %s %02d %02d:%02d:%02d %04d\"\n"
#else
		"# define BUILD_CTIME \"%s %s %02d %02d:%02d:%02d %s %04d\"\n"
#endif
		"# define BUILD_USER \"%s\"\n"
		"# define BUILD_HOST \"%s\"\n"
		"# define BUILD_DOMAIN \"%s\"\n"
		"# define BUILD_SERIAL %d\n"
		"\n"
		"# endif /* _build_h */\n",
		now->tm_wday == 0 ? 7 : now->tm_wday, 
		now->tm_mday, 
		now->tm_mon + 1, 
		now->tm_year + 1900,
		now->tm_hour, 
		now->tm_min, 
		now->tm_sec,
		wdays[now->tm_wday], months[now->tm_mon],
		now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec,
#ifndef __CYGWIN__
		now->tm_zone,
#endif
		now->tm_year + 1900,
		user,
		host,
		domain,
		1
	);
	
	if (ferror (out) != 0)
	{
		fprintf (stderr, "%s: write error on `%s': %s\n",
			myname, OUTNAME, strerror (errno));
		
		(void) unlink (OUTNAME);
		return 1;    
	}
	
	if (fclose (out) != 0)
	{
		fprintf (stderr, "%s: error: can't close `%s': %s\n",
			myname, OUTNAME, strerror (errno));
		
		(void) unlink (OUTNAME);
		return 1;    
	}
	
	return 0;
}

void
signal_handler (int signum)
{
	if (killfile != NULL)
		(void) unlink (killfile);
}
