More portable signature check.
[wine] / debugger / ext_debugger.c
1 /* 
2  * Convenience functions to handle use of external debugger.
3  *
4  * Copyright 1999 Kevin Holbrook
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21
22 #include <unistd.h>
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #define DBG_BUFF_SIZE  12
29
30 #define DBG_EXTERNAL_DEFAULT   "gdb"
31 #define DBG_LOCATION_DEFAULT   "/usr/local/bin/wine"
32 #define DBG_SLEEPTIME_DEFAULT  120
33
34
35
36 /* DEBUG_ExternalDebugger
37  *
38  * This function invokes an external debugger on the current
39  * wine process. The form of the command executed is:
40  *  <debugger image> <wine image> <attach process id>
41  *
42  * The debugger command is normally invoked by a newly created xterm.
43  *
44  * The current calling process is temporarily put to sleep
45  * so that the invoked debugger has time to come up and attach.
46  *
47  * The following environment variables may be used:
48  *
49  *   Name                Use                                      Default
50  *  -------------------------------------------------------------------------------------
51  *   WINE_DBG_EXTERNAL   debugger command to invoke               ("gdb")
52  *   WINE_DBG_LOCATION   fully qualified location of wine image   ("/usr/local/bin/wine")
53  *   WINE_DBG_NO_XTERM   if set do not invoke xterm with command  (not set)
54  *   WINE_DBG_SLEEPTIME  number of seconds to make process sleep  (120)
55  *
56  *
57  * Usage:
58  *
59  *   #include "wine/debug.h"
60  *
61  *   DEBUG_ExternalDebugger();
62  *
63  *
64  * Environment Example:
65  *
66  *   export WINE_DBG_EXTERNAL="ddd"
67  *   export WINE_DBG_NO_XTERM=1
68  *   export WINE_DBG_SLEEPTIME=60
69  *
70  */
71
72 void DEBUG_ExternalDebugger(void)
73 {
74   pid_t attach_pid;
75   pid_t child_pid;
76   int   dbg_sleep_secs = DBG_SLEEPTIME_DEFAULT;
77   char *dbg_sleeptime;
78
79
80   dbg_sleeptime = getenv("WINE_DBG_SLEEPTIME");
81
82   /* convert sleep time string to integer seconds */
83   if (dbg_sleeptime)
84   {
85     dbg_sleep_secs = atoi(dbg_sleeptime);
86
87     /* check for conversion error */
88     if (dbg_sleep_secs == 0)
89       dbg_sleep_secs = DBG_SLEEPTIME_DEFAULT;
90   }
91
92   /* get the current process id */
93   attach_pid = getpid();
94
95   /* create new process */
96   child_pid = fork();
97
98   /* check if we are the child process */
99   if (child_pid == 0)
100   {
101     int  status;
102     const char *dbg_external;
103     const char *dbg_wine_location;
104     const char *dbg_no_xterm;
105     char pid_string[DBG_BUFF_SIZE];    
106
107
108     /* check settings in environment for debugger to use */
109     dbg_external      = getenv("WINE_DBG_EXTERNAL");
110     dbg_wine_location = getenv("WINE_DBG_LOCATION");
111     dbg_no_xterm      = getenv("WINE_DBG_NO_XTERM");
112
113     /* if not set in environment, use default */
114     if (!dbg_external)
115       dbg_external = "gdb";
116
117     /* if not set in environment, use default */
118     if (!dbg_wine_location)
119       dbg_wine_location = "wine";
120
121     /* check for empty string in WINE_DBG_NO_XTERM */
122     if (dbg_no_xterm && (strlen(dbg_no_xterm) < 1))
123       dbg_no_xterm = NULL;
124
125     /* clear the buffer */
126     memset(pid_string, 0, DBG_BUFF_SIZE);
127
128     /* make pid into string */
129     sprintf(pid_string, "%ld", (long) attach_pid);
130
131     /* now exec the debugger to get it's own clean memory space */
132     if (dbg_no_xterm)
133       status = execlp(dbg_external, dbg_external, dbg_wine_location, pid_string, NULL);
134     else
135       status = execlp("xterm", "xterm", "-e", dbg_external, dbg_wine_location, pid_string, NULL); 
136
137     if (status == -1)
138     {
139       if (dbg_no_xterm)
140         fprintf(stderr, "DEBUG_ExternalDebugger failed to execute \"%s %s %s\" (%s)\n", 
141                 dbg_external, dbg_wine_location, pid_string, strerror(errno));
142       else
143         fprintf(stderr, "DEBUG_ExternalDebugger failed to execute \"xterm -e %s %s %s\" (%s)\n", 
144                 dbg_external, dbg_wine_location, pid_string, strerror(errno));
145     }
146
147   }
148   else if (child_pid != -1)
149   {
150     /* make the parent/caller sleep so the child/debugger can catch it */
151     sleep(dbg_sleep_secs);
152   }
153   else
154     fprintf(stderr, "DEBUG_ExternalDebugger failed.\n");
155   
156 }
157
158