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