





#define GDBHOOK_DEBUGGER			"gdb"
#define GDBHOOK_MODE				"GDBHOOK_MODE"
#define GDBHOOK_BELL_COUNT			"GDBHOOK_BELL_COUNT"
#define GDBHOOK_STD_BELL_COUNT		4
#define GDBHOOK_STDPREFIX			"sig-hook"
#define GDBHOOK_WAIT				"GDBHOOK_WAIT"
#define GDBHOOK_STD_WAIT			4









static int
DbghWaitProc(char const * pszFileName);

static void
DbghSigHandler(int iSignal);

static int
DbghCleanupFiles(char const * pszPath);






static char	szProgram[256] = "",
			szPath[256] = "";








static int
DbghWaitProc(char const * pszFileName)
{

	char const *	pszBellCnt = getenv(GDBHOOK_BELL_COUNT);
	int	iBellCnt = (pszBellCnt != NULL) ? atoi(pszBellCnt): GDBHOOK_STD_BELL_COUNT;
   	char const *	pszWait = getenv(GDBHOOK_WAIT);
   	int	iWait = (pszWait != NULL) ? atoi(pszWait): GDBHOOK_STD_WAIT;
   	volatile int	iLoop = 0;

   	while (!iLoop && (access(pszFileName, F_OK) == 0))
   	{
   		if (iBellCnt > 0)
   			fprintf(stderr, "%c", 7), --iBellCnt;

		sleep(iWait);
	}

	return (0);

}



static void
DbghSigHandler(int iSignal)
{

	char const *	pszEnvVar = getenv(GDBHOOK_MODE);

	if ((pszEnvVar != NULL) && atoi(pszEnvVar))
	{
		char	szDbgFile[256] = "";

		sprintf(szDbgFile, "%s%s.%d.%u.hook", szPath, GDBHOOK_STDPREFIX, iSignal, getpid());

		FILE *	pFile = fopen(szDbgFile, "w");

		if (pFile != NULL)
		{
			time_t	tFault = time(NULL);

#ifdef SOLARIS

			fprintf(pFile,
   					"#!/bin/sh\n"
   					"#\n"
   					"# Signal = %s (%d)\n"
   					"# Time   = %s"
   					"# Pid    = %u\n"
   					"#\n"
   					"%s %s %u\n\n",
   					(iSignal < _sys_nsig) ? _sys_siglist[iSignal]: "????", iSignal, ctime(&tFault),
   					getpid(), GDBHOOK_DEBUGGER, szProgram, getpid());

#else // #ifdef SOLARIS

			fprintf(pFile,
   					"#!/bin/sh\n"
   					"#\n"
   					"# Signal = %s (%d)\n"
   					"# Time   = %s"
   					"# Pid    = %u\n"
   					"#\n"
   					"%s %s %u\n\n",
   					(iSignal < _NSIG) ? _sys_siglist[iSignal]: "????", iSignal, ctime(&tFault),
   					getpid(), GDBHOOK_DEBUGGER, szProgram, getpid());

#endif // #ifdef SOLARIS

   			fclose(pFile);


   			chmod(szDbgFile, 0755);


   			DbghWaitProc(szDbgFile);


   			signal(iSignal, SIG_DFL);
	   	}
	}
	else
		signal(iSignal, SIG_DFL);

}



static int
DbghCleanupFiles(char const * pszPath)
{

	glob_t 	globbuf;
	char	szPattern[256] = "";

	sprintf(szPattern, "%s*.hook", pszPath);

	if (glob(szPattern, 0, NULL, &globbuf) == 0)
	{

		for (int ii = 0; ii < globbuf.gl_pathc; ii++)
			unlink(globbuf.gl_pathv[ii]);

	}

	globfree(&globbuf);

	return (0);

}



int
DbghInit(char const * pszProgram)
{

	strcpy(szProgram, pszProgram);

	char const *	pszSlash = strrchr(pszProgram, '/');

	if (pszSlash != NULL)
	{
		int	iPathLength = (int) (pszSlash - pszProgram) + 1;

		strncpy(szPath, pszProgram, iPathLength);
	    szPath[iPathLength] = '\0';
	}
	else
		strcpy(szPath, "./");


	if (DbghCleanupFiles(szPath) < 0)
		return (-1);


	return (0);

}



int
DbghInstall(void)
{

	signal(SIGSEGV, DbghSigHandler);
	signal(SIGBUS, DbghSigHandler);
	signal(SIGFPE, DbghSigHandler);

#ifdef LINUX
	signal(SIGSTKFLT, DbghSigHandler);
#endif // #ifdef LINUX

	signal(SIGABRT, DbghSigHandler);

	return (0);

}



int
DbghWaitPoint(char const * pszName)
{

	char const *	pszEnvVar = getenv(GDBHOOK_MODE);

	if ((pszEnvVar != NULL) && atoi(pszEnvVar))
	{
		char	szDbgFile[256] = "";

		sprintf(szDbgFile, "%s%s.%u.hook", szPath, pszName, getpid());

		FILE *	pFile = fopen(szDbgFile, "w");

		if (pFile != NULL)
		{
			time_t	tFault = time(NULL);

			fprintf(pFile,
   					"#!/bin/sh\n"
   					"#\n"
   					"# Time   = %s"
   					"# Pid    = %u\n"
   					"#\n"
   					"%s %s %u\n\n",
   					ctime(&tFault), getpid(), GDBHOOK_DEBUGGER, szProgram, getpid());
   	
   			fclose(pFile);

   			
   			chmod(szDbgFile, 0755);

   			
   			DbghWaitProc(szDbgFile);
   			
	   	}
	}

	return (0);

}



int
DbghCleanup(void)
{


	return (0);

}

