Make setting DISPLAY work

And remove a bunch of grotty code to manipulate an environment
array at the same time. Instead, simply call setenv in the child_setup
function.
This commit is contained in:
Matthias Clasen 2009-06-10 16:20:51 -04:00
parent 0981552099
commit 12c411a98e

View File

@ -823,125 +823,6 @@ prepend_terminal_to_vector (int *argc,
#endif /* G_OS_WIN32 */ #endif /* G_OS_WIN32 */
} }
/* '=' is the new '\0'.
* DO NOT CALL unless at least one string ends with '='
*/
static gboolean
is_env (const char *a,
const char *b)
{
while (*a == *b)
{
if (*a == 0 || *b == 0)
return FALSE;
if (*a == '=')
return TRUE;
a++;
b++;
}
return FALSE;
}
/* free with g_strfreev */
static char **
replace_env_var (char **old_environ,
const char *env_var,
const char *new_value)
{
int length, new_length;
int index, new_index;
char **new_environ;
int i, new_i;
/* do two things at once:
* - discover the length of the environment ('length')
* - find the location (if any) of the env var ('index')
*/
index = -1;
for (length = 0; old_environ[length]; length++)
{
/* if we already have it in our environment, replace */
if (is_env (old_environ[length], env_var))
index = length;
}
/* no current env var, no desired env value.
* this is easy :)
*/
if (new_value == NULL && index == -1)
return old_environ;
/* in all cases now, we will be using a modified environment.
* determine its length and allocated it.
*
* after this block:
* new_index = location to insert, if any
* new_length = length of the new array
* new_environ = the pointer array for the new environment
*/
if (new_value == NULL && index >= 0)
{
/* in this case, we will be removing an entry */
new_length = length - 1;
new_index = -1;
}
else if (new_value != NULL && index < 0)
{
/* in this case, we will be adding an entry to the end */
new_length = length + 1;
new_index = length;
}
else
/* in this case, we will be replacing the existing entry */
{
new_length = length;
new_index = index;
}
new_environ = g_malloc (sizeof (char *) * (new_length + 1));
new_environ[new_length] = NULL;
/* now we do the copying.
* for each entry in the new environment, we decide what to do
*/
i = 0;
for (new_i = 0; new_i < new_length; new_i++)
{
if (new_i == new_index)
{
/* insert our new item */
new_environ[new_i] = g_strconcat (env_var,
"=",
new_value,
NULL);
/* if we had an old entry, skip it now */
if (index >= 0)
i++;
}
else
{
/* if this is the old DESKTOP_STARTUP_ID, skip it */
if (i == index)
i++;
/* copy an old item */
new_environ[new_i] = g_strdup (old_environ[i]);
i++;
}
}
g_strfreev (old_environ);
return new_environ;
}
static GList * static GList *
uri_list_segment_to_files (GList *start, uri_list_segment_to_files (GList *start,
GList *end) GList *end)
@ -960,15 +841,27 @@ uri_list_segment_to_files (GList *start,
return g_list_reverse (res); return g_list_reverse (res);
} }
#ifdef HAVE__NSGETENVIRON typedef struct
#define environ (*_NSGetEnviron()) {
#elif !defined(G_OS_WIN32) const char *display;
const char *sn_id;
} ChildSetupData;
/* According to the Single Unix Specification, environ is not in static void
* * any system header, although unistd.h often declares it. child_setup (gpointer user_data)
* */ {
extern char **environ; ChildSetupData *data = user_data;
#endif
if (data->display)
g_setenv ("DISPLAY", data->display, TRUE);
else
g_unsetenv ("DISPLAY");
if (data->sn_id)
g_setenv ("DESKTOP_STARTUP_ID", data->sn_id, TRUE);
else
g_unsetenv ("DESKTOP_STARTUP_ID");
}
static gboolean static gboolean
g_desktop_app_info_launch_uris (GAppInfo *appinfo, g_desktop_app_info_launch_uris (GAppInfo *appinfo,
@ -980,16 +873,13 @@ g_desktop_app_info_launch_uris (GAppInfo *appinfo,
gboolean completed = FALSE; gboolean completed = FALSE;
GList *old_uris; GList *old_uris;
GList *launched_files; GList *launched_files;
char **envp;
char **argv; char **argv;
int argc; int argc;
char *display; ChildSetupData data;
char *sn_id;
g_return_val_if_fail (appinfo != NULL, FALSE); g_return_val_if_fail (appinfo != NULL, FALSE);
argv = NULL; argv = NULL;
envp = NULL;
do do
{ {
@ -1005,70 +895,47 @@ g_desktop_app_info_launch_uris (GAppInfo *appinfo,
goto out; goto out;
} }
sn_id = NULL; data.display = NULL;
data.sn_id = NULL;
if (launch_context) if (launch_context)
{ {
launched_files = uri_list_segment_to_files (old_uris, uris); launched_files = uri_list_segment_to_files (old_uris, uris);
display = g_app_launch_context_get_display (launch_context, data.display = g_app_launch_context_get_display (launch_context,
appinfo, appinfo,
launched_files); launched_files);
sn_id = NULL;
if (info->startup_notify) if (info->startup_notify)
sn_id = g_app_launch_context_get_startup_notify_id (launch_context, data.sn_id = g_app_launch_context_get_startup_notify_id (launch_context,
appinfo, appinfo,
launched_files); launched_files);
if (display || sn_id)
{
#ifdef G_OS_WIN32
/* FIXME */
envp = g_new0 (char *, 1);
#else
envp = g_strdupv (environ);
#endif
if (display)
envp = replace_env_var (envp,
"DISPLAY",
display);
if (sn_id)
envp = replace_env_var (envp,
"DESKTOP_STARTUP_ID",
sn_id);
}
g_free (display);
g_list_foreach (launched_files, (GFunc)g_object_unref, NULL); g_list_foreach (launched_files, (GFunc)g_object_unref, NULL);
g_list_free (launched_files); g_list_free (launched_files);
} }
if (!g_spawn_async (info->path, /* working directory */ if (!g_spawn_async (info->path,
argv, argv,
envp, NULL,
G_SPAWN_SEARCH_PATH /* flags */, G_SPAWN_SEARCH_PATH,
NULL /* child_setup */, child_setup,
NULL /* data */, &data,
NULL /* child_pid */, NULL,
error)) error))
{ {
if (sn_id) if (data.sn_id)
{ g_app_launch_context_launch_failed (launch_context, data.sn_id);
g_app_launch_context_launch_failed (launch_context, sn_id);
g_free (sn_id); g_free (data.sn_id);
} g_free (data.display);
goto out; goto out;
} }
g_free (data.sn_id);
g_free (data.display);
g_free (sn_id);
g_strfreev (envp);
g_strfreev (argv); g_strfreev (argv);
envp = NULL;
argv = NULL; argv = NULL;
} }
while (uris != NULL); while (uris != NULL);
@ -1077,7 +944,6 @@ g_desktop_app_info_launch_uris (GAppInfo *appinfo,
out: out:
g_strfreev (argv); g_strfreev (argv);
g_strfreev (envp);
return completed; return completed;
} }