]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkspawn-x11.c
Check for crt_extern.h and _NSGetEnviron. Fix compilation on Darwin where
[~andy/gtk] / gdk / x11 / gdkspawn-x11.c
1 /*
2  * Copyright (C) 2003 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Authors: Mark McLoughlin <mark@skynet.ie>
20  */
21
22 #include <config.h>
23 #include <string.h>
24
25 #ifdef HAVE_CRT_EXTERNS_H 
26 #include <crt_externs.h> /* for _NSGetEnviron */
27 #endif
28
29 #include "gdkspawn.h"
30
31 #include <glib.h>
32 #include <gdk/gdk.h>
33 #include "gdkalias.h"
34   
35 #ifdef HAVE__NSGETENVIRON
36 #define environ (*_NSGetEnviron())
37 #else
38
39 /* According to the Single Unix Specification, environ is not in 
40  * any system header, although unistd.h often declares it.
41  */
42 extern char **environ;
43 #endif
44
45 /**
46  * gdk_make_spawn_environment_for_screen:
47  * @screen: A #GdkScreen
48  * @envp: program environment to copy, or %NULL to use current environment.
49  *
50  * Returns a modified copy of the program environment @envp (or the current
51  * environment if @envp is %NULL) with <envar>DISPLAY</envar> set such that 
52  * a launched application (which calls gdk_display_open()) inheriting this 
53  * environment would have @screen as its default screen..
54  *
55  * Returns: a newly-allocated %NULL-terminated array of strings.
56  *          Use g_strfreev() to free it.
57  *
58  * Since: 2.4
59  **/
60 static gchar **
61 gdk_spawn_make_environment_for_screen (GdkScreen  *screen,
62                                        gchar     **envp)
63 {
64   gchar **retval = NULL;
65   gchar  *display_name;
66   gint    display_index = -1;
67   gint    i, env_len;
68
69   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
70
71   if (envp == NULL)
72     envp = environ;
73
74   for (env_len = 0; envp[env_len]; env_len++)
75     if (strncmp (envp[env_len], "DISPLAY", strlen ("DISPLAY")) == 0)
76       display_index = env_len;
77
78   retval = g_new (char *, env_len + 1);
79   retval[env_len] = NULL;
80
81   display_name = gdk_screen_make_display_name (screen);
82
83   for (i = 0; i < env_len; i++)
84     if (i == display_index)
85       retval[i] = g_strconcat ("DISPLAY=", display_name, NULL);
86     else
87       retval[i] = g_strdup (envp[i]);
88
89   g_assert (i == env_len);
90
91   g_free (display_name);
92
93   return retval;
94 }
95
96 /**
97  * gdk_spawn_on_screen:
98  * @screen: a #GdkScreen
99  * @working_directory: child's current working directory, or %NULL to 
100  *   inherit parent's
101  * @argv: child's argument vector
102  * @envp: child's environment, or %NULL to inherit parent's
103  * @flags: flags from #GSpawnFlags
104  * @child_setup: function to run in the child just before exec()
105  * @user_data: user data for @child_setup
106  * @child_pid: return location for child process ID, or %NULL
107  * @error: return location for error
108  *
109  * Like g_spawn_async(), except the child process is spawned in such
110  * an environment that on calling gdk_display_open() it would be
111  * returned a #GdkDisplay with @screen as the default screen.
112  *
113  * This is useful for applications which wish to launch an application
114  * on a specific screen.
115  *
116  * Return value: %TRUE on success, %FALSE if error is set
117  *
118  * Since: 2.4
119  **/
120 gboolean
121 gdk_spawn_on_screen (GdkScreen             *screen,
122                      const gchar           *working_directory,
123                      gchar                **argv,
124                      gchar                **envp,
125                      GSpawnFlags            flags,
126                      GSpawnChildSetupFunc   child_setup,
127                      gpointer               user_data,
128                      gint                  *child_pid,
129                      GError               **error)
130 {
131   gchar    **new_envp;
132   gboolean   retval;
133
134   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
135
136   new_envp = gdk_spawn_make_environment_for_screen (screen, envp);
137
138   retval = g_spawn_async (working_directory,
139                           argv,
140                           new_envp,
141                           flags,
142                           child_setup,
143                           user_data,
144                           child_pid,
145                           error);
146
147   g_strfreev (new_envp);
148
149   return retval;
150 }
151
152 /**
153  * gdk_spawn_on_screen_with_pipes:
154  * @screen: a #GdkScreen
155  * @working_directory: child's current working directory, or %NULL to 
156  *   inherit parent's
157  * @argv: child's argument vector
158  * @envp: child's environment, or %NULL to inherit parent's
159  * @flags: flags from #GSpawnFlags
160  * @child_setup: function to run in the child just before exec()
161  * @user_data: user data for @child_setup
162  * @child_pid: return location for child process ID, or %NULL
163  * @standard_input: return location for file descriptor to write to 
164  *   child's stdin, or %NULL
165  * @standard_output: return location for file descriptor to read child's 
166  *   stdout, or %NULL
167  * @standard_error: return location for file descriptor to read child's 
168  *   stderr, or %NULL
169  * @error: return location for error
170  *
171  * Like g_spawn_async_with_pipes(), except the child process is
172  * spawned in such an environment that on calling gdk_display_open()
173  * it would be returned a #GdkDisplay with @screen as the default
174  * screen.
175  *
176  * This is useful for applications which wish to launch an application
177  * on a specific screen.
178  *
179  * Return value: %TRUE on success, %FALSE if an error was set
180  *
181  * Since: 2.4
182  **/
183 gboolean
184 gdk_spawn_on_screen_with_pipes (GdkScreen            *screen,
185                                 const gchar          *working_directory,
186                                 gchar               **argv,
187                                 gchar               **envp,
188                                 GSpawnFlags           flags,
189                                 GSpawnChildSetupFunc  child_setup,
190                                 gpointer              user_data,
191                                 gint                 *child_pid,
192                                 gint                 *standard_input,
193                                 gint                 *standard_output,
194                                 gint                 *standard_error,
195                                 GError              **error)
196 {
197   gchar    **new_envp;
198   gboolean   retval;
199
200   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
201
202   new_envp = gdk_spawn_make_environment_for_screen (screen, envp);
203
204   retval = g_spawn_async_with_pipes (working_directory,
205                                      argv,
206                                      new_envp,
207                                      flags,
208                                      child_setup,
209                                      user_data,
210                                      child_pid,
211                                      standard_input,
212                                      standard_output,
213                                      standard_error,
214                                      error);
215
216   g_strfreev (new_envp);
217
218   return retval;
219 }
220
221 /**
222  * gdk_spawn_command_line_on_screen:
223  * @screen: a #GdkScreen
224  * @command_line: a command line
225  * @error: return location for errors
226  *
227  * Like g_spawn_command_line_async(), except the child process is
228  * spawned in such an environment that on calling gdk_display_open()
229  * it would be returned a #GdkDisplay with @screen as the default
230  * screen.
231  *
232  * This is useful for applications which wish to launch an application
233  * on a specific screen.
234  *
235  * Return value: %TRUE on success, %FALSE if error is set.
236  *
237  * Since: 2.4
238  **/
239 gboolean
240 gdk_spawn_command_line_on_screen (GdkScreen    *screen,
241                                   const gchar  *command_line,
242                                   GError      **error)
243 {
244   gchar    **argv = NULL;
245   gboolean   retval;
246
247   g_return_val_if_fail (command_line != NULL, FALSE);
248
249   if (!g_shell_parse_argv (command_line,
250                            NULL, &argv,
251                            error))
252     return FALSE;
253
254   retval = gdk_spawn_on_screen (screen,
255                                 NULL, argv, NULL,
256                                 G_SPAWN_SEARCH_PATH,
257                                 NULL, NULL, NULL,
258                                 error);
259   g_strfreev (argv);
260
261   return retval;
262 }
263
264 #define __GDK_SPAWN_X11_C__
265 #include "gdkaliasdef.c"