Prevent endless loop in except2.
[wine] / debugger / external.c
1 /* 
2  *  File    : external.c
3  *  Author  : Kevin Holbrook
4  *  Created : July 18, 1999
5  *
6  *  Convenience functions to handle use of external debugger.
7  *
8  */
9
10
11 #include <unistd.h>
12 #include <errno.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16
17
18
19 #define DBG_BUFF_SIZE  12
20
21 #define DBG_EXTERNAL_DEFAULT   "gdb"
22 #define DBG_LOCATION_DEFAULT   "/usr/local/bin/wine"
23 #define DBG_SLEEPTIME_DEFAULT  120
24
25
26
27 /* DEBUG_ExternalDebugger
28  *
29  * This function invokes an external debugger on the current
30  * wine process. The form of the command executed is:
31  *  <debugger image> <wine image> <attach process id>
32  *
33  * The debugger command is normally invoked by a newly created xterm.
34  *
35  * The current calling process is temporarily put to sleep
36  * so that the invoked debugger has time to come up and attach.
37  *
38  * The following environment variables may be used:
39  *
40  *   Name                Use                                      Default
41  *  -------------------------------------------------------------------------------------
42  *   WINE_DBG_EXTERNAL   debugger command to invoke               ("gdb")
43  *   WINE_DBG_LOCATION   fully qualified location of wine image   ("/usr/local/bin/wine")
44  *   WINE_DBG_NO_XTERM   if set do not invoke xterm with command  (not set)
45  *   WINE_DBG_SLEEPTIME  number of seconds to make process sleep  (120)
46  *
47  *
48  * Usage:
49  *
50  *   #include "debugtools.h"
51  *
52  *   DEBUG_ExternalDebugger();
53  *
54  *
55  * Environment Example:
56  *
57  *   export WINE_DBG_EXTERNAL="ddd"
58  *   export WINE_DBG_NO_XTERM=1
59  *   export WINE_DBG_SLEEPTIME=60
60  *
61  */
62
63 void DEBUG_ExternalDebugger(void)
64 {
65   pid_t attach_pid;
66   pid_t child_pid;
67   int   dbg_sleep_secs = DBG_SLEEPTIME_DEFAULT;
68   char *dbg_sleeptime;
69
70
71   dbg_sleeptime = getenv("WINE_DBG_SLEEPTIME");
72
73   /* convert sleep time string to integer seconds */
74   if (dbg_sleeptime)
75   {
76     dbg_sleep_secs = atoi(dbg_sleeptime);
77
78     /* check for conversion error */
79     if (dbg_sleep_secs == 0)
80       dbg_sleep_secs = DBG_SLEEPTIME_DEFAULT;
81   }
82
83   /* get the curent process id */
84   attach_pid = getpid();
85
86   /* create new process */
87   child_pid = fork();
88
89   /* check if we are the child process */
90   if (child_pid == 0)
91   {
92     int  status;
93     char *dbg_external;
94     char *dbg_wine_location;
95     char *dbg_no_xterm;
96     char pid_string[DBG_BUFF_SIZE];    
97
98
99     /* check settings in environment for debugger to use */
100     dbg_external      = getenv("WINE_DBG_EXTERNAL");
101     dbg_wine_location = getenv("WINE_DBG_LOCATION");
102     dbg_no_xterm      = getenv("WINE_DBG_NO_XTERM");
103
104     /* if not set in environment, use default */
105     if (!dbg_external)
106       dbg_external = "gdb";
107
108     /* if not set in environment, use default */
109     if (!dbg_wine_location)
110       dbg_wine_location = "/usr/local/bin/wine";
111
112     /* check for empty string in WINE_DBG_NO_XTERM */
113     if (dbg_no_xterm && (strlen(dbg_no_xterm) < 1))
114       dbg_no_xterm = NULL;
115
116     /* clear the buffer */
117     memset(pid_string, 0, DBG_BUFF_SIZE);
118
119     /* make pid into string */
120     sprintf(pid_string, "%ld", (long) attach_pid);
121
122     /* now exec the debugger to get it's own clean memory space */
123     if (dbg_no_xterm)
124       status = execlp(dbg_external, dbg_external, dbg_wine_location, pid_string, NULL);
125     else
126       status = execlp("xterm", "xterm", "-e", dbg_external, dbg_wine_location, pid_string, NULL); 
127
128     if (status == -1)
129     {
130       if (dbg_no_xterm)
131         fprintf(stderr, "DEBUG_ExternalDebugger failed to execute \"%s %s %s\", errno = %d\n", 
132                 dbg_external, dbg_wine_location, pid_string, errno);
133       else
134         fprintf(stderr, "DEBUG_ExternalDebugger failed to execute \"xterm -e %s %s %s\", errno = %d\n", 
135                 dbg_external, dbg_wine_location, pid_string, errno);
136     }
137
138   }
139   else if (child_pid != -1)
140   {
141     /* make the parent/caller sleep so the child/debugger can catch it */
142     sleep(dbg_sleep_secs);
143   }
144   else
145     fprintf(stderr, "DEBUG_ExternalDebugger failed.\n");
146   
147 }
148
149