1999-07-24 12:07:35 +00:00
|
|
|
/*
|
|
|
|
* File : external.c
|
|
|
|
* Author : Kevin Holbrook
|
|
|
|
* Created : July 18, 1999
|
|
|
|
*
|
|
|
|
* Convenience functions to handle use of external debugger.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2000-01-30 21:16:45 +00:00
|
|
|
#include "options.h"
|
1999-07-24 12:07:35 +00:00
|
|
|
|
|
|
|
#define DBG_BUFF_SIZE 12
|
|
|
|
|
|
|
|
#define DBG_EXTERNAL_DEFAULT "gdb"
|
|
|
|
#define DBG_LOCATION_DEFAULT "/usr/local/bin/wine"
|
|
|
|
#define DBG_SLEEPTIME_DEFAULT 120
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* DEBUG_ExternalDebugger
|
|
|
|
*
|
|
|
|
* This function invokes an external debugger on the current
|
|
|
|
* wine process. The form of the command executed is:
|
|
|
|
* <debugger image> <wine image> <attach process id>
|
|
|
|
*
|
|
|
|
* The debugger command is normally invoked by a newly created xterm.
|
|
|
|
*
|
|
|
|
* The current calling process is temporarily put to sleep
|
|
|
|
* so that the invoked debugger has time to come up and attach.
|
|
|
|
*
|
|
|
|
* The following environment variables may be used:
|
|
|
|
*
|
|
|
|
* Name Use Default
|
|
|
|
* -------------------------------------------------------------------------------------
|
|
|
|
* WINE_DBG_EXTERNAL debugger command to invoke ("gdb")
|
|
|
|
* WINE_DBG_LOCATION fully qualified location of wine image ("/usr/local/bin/wine")
|
|
|
|
* WINE_DBG_NO_XTERM if set do not invoke xterm with command (not set)
|
|
|
|
* WINE_DBG_SLEEPTIME number of seconds to make process sleep (120)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Usage:
|
|
|
|
*
|
|
|
|
* #include "debugtools.h"
|
|
|
|
*
|
|
|
|
* DEBUG_ExternalDebugger();
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Environment Example:
|
|
|
|
*
|
|
|
|
* export WINE_DBG_EXTERNAL="ddd"
|
|
|
|
* export WINE_DBG_NO_XTERM=1
|
|
|
|
* export WINE_DBG_SLEEPTIME=60
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
void DEBUG_ExternalDebugger(void)
|
|
|
|
{
|
|
|
|
pid_t attach_pid;
|
|
|
|
pid_t child_pid;
|
|
|
|
int dbg_sleep_secs = DBG_SLEEPTIME_DEFAULT;
|
|
|
|
char *dbg_sleeptime;
|
|
|
|
|
|
|
|
|
|
|
|
dbg_sleeptime = getenv("WINE_DBG_SLEEPTIME");
|
|
|
|
|
|
|
|
/* convert sleep time string to integer seconds */
|
|
|
|
if (dbg_sleeptime)
|
|
|
|
{
|
|
|
|
dbg_sleep_secs = atoi(dbg_sleeptime);
|
|
|
|
|
|
|
|
/* check for conversion error */
|
|
|
|
if (dbg_sleep_secs == 0)
|
|
|
|
dbg_sleep_secs = DBG_SLEEPTIME_DEFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the curent process id */
|
|
|
|
attach_pid = getpid();
|
|
|
|
|
|
|
|
/* create new process */
|
|
|
|
child_pid = fork();
|
|
|
|
|
|
|
|
/* check if we are the child process */
|
|
|
|
if (child_pid == 0)
|
|
|
|
{
|
|
|
|
int status;
|
2000-01-30 21:16:45 +00:00
|
|
|
const char *dbg_external;
|
|
|
|
const char *dbg_wine_location;
|
|
|
|
const char *dbg_no_xterm;
|
1999-07-24 12:07:35 +00:00
|
|
|
char pid_string[DBG_BUFF_SIZE];
|
|
|
|
|
|
|
|
|
|
|
|
/* check settings in environment for debugger to use */
|
|
|
|
dbg_external = getenv("WINE_DBG_EXTERNAL");
|
|
|
|
dbg_wine_location = getenv("WINE_DBG_LOCATION");
|
|
|
|
dbg_no_xterm = getenv("WINE_DBG_NO_XTERM");
|
|
|
|
|
|
|
|
/* if not set in environment, use default */
|
|
|
|
if (!dbg_external)
|
|
|
|
dbg_external = "gdb";
|
|
|
|
|
|
|
|
/* if not set in environment, use default */
|
|
|
|
if (!dbg_wine_location)
|
2000-01-30 21:16:45 +00:00
|
|
|
dbg_wine_location = argv0;
|
1999-07-24 12:07:35 +00:00
|
|
|
|
|
|
|
/* check for empty string in WINE_DBG_NO_XTERM */
|
|
|
|
if (dbg_no_xterm && (strlen(dbg_no_xterm) < 1))
|
|
|
|
dbg_no_xterm = NULL;
|
|
|
|
|
|
|
|
/* clear the buffer */
|
|
|
|
memset(pid_string, 0, DBG_BUFF_SIZE);
|
|
|
|
|
|
|
|
/* make pid into string */
|
1999-07-31 13:13:23 +00:00
|
|
|
sprintf(pid_string, "%ld", (long) attach_pid);
|
1999-07-24 12:07:35 +00:00
|
|
|
|
|
|
|
/* now exec the debugger to get it's own clean memory space */
|
|
|
|
if (dbg_no_xterm)
|
|
|
|
status = execlp(dbg_external, dbg_external, dbg_wine_location, pid_string, NULL);
|
|
|
|
else
|
|
|
|
status = execlp("xterm", "xterm", "-e", dbg_external, dbg_wine_location, pid_string, NULL);
|
|
|
|
|
|
|
|
if (status == -1)
|
|
|
|
{
|
|
|
|
if (dbg_no_xterm)
|
2000-08-26 20:31:48 +00:00
|
|
|
fprintf(stderr, "DEBUG_ExternalDebugger failed to execute \"%s %s %s\" (%s)\n",
|
|
|
|
dbg_external, dbg_wine_location, pid_string, strerror(errno));
|
1999-07-24 12:07:35 +00:00
|
|
|
else
|
2000-08-26 20:31:48 +00:00
|
|
|
fprintf(stderr, "DEBUG_ExternalDebugger failed to execute \"xterm -e %s %s %s\" (%s)\n",
|
|
|
|
dbg_external, dbg_wine_location, pid_string, strerror(errno));
|
1999-07-24 12:07:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (child_pid != -1)
|
|
|
|
{
|
|
|
|
/* make the parent/caller sleep so the child/debugger can catch it */
|
|
|
|
sleep(dbg_sleep_secs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fprintf(stderr, "DEBUG_ExternalDebugger failed.\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|