/* egg-screen-exec.c
*
* Copyright (C) 2002 Sun Microsystems Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Mark McLoughlin <mark@skynet.ie>
*/
#include <config.h>
#include "egg-screen-exec.h"
#include <string.h>
#include <libgnome/gnome-exec.h>
#ifndef HAVE_GTK_MULTIHEAD
#include <gdk/gdkx.h>
#endif
extern char **environ;
/**
* egg_screen_exec_display_string:
* @screen: A #GdkScreen
*
* Description: Returns a string that when passed to XOpenDisplay()
* would cause @screen to be the default screen on the newly opened
* X display. This string is suitable for setting $DISPLAY when
* launching an application which should appear on @screen.
*
* Returns: a newly allocated string or %NULL on error.
**/
char *
egg_screen_exec_display_string (GdkScreen *screen)
{
#ifdef HAVE_GTK_MULTIHEAD
GString *str;
const char *old_display;
char *retval;
char *p;
g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
if (gdk_screen_get_default () == screen)
return g_strdup_printf ("DISPLAY=%s",
gdk_display_get_name (
gdk_screen_get_display (screen)));
old_display = gdk_display_get_name (gdk_screen_get_display (screen));
str = g_string_new ("DISPLAY=");
g_string_append (str, old_display);
p = strrchr (str->str, '.');
if (p && p > strchr (str->str, ':'))
g_string_truncate (str, p - str->str);
g_string_append_printf (str, ".%d", gdk_screen_get_number (screen));
retval = str->str;
g_string_free (str, FALSE);
return retval;
#else
return g_strdup (DisplayString (GDK_DISPLAY ()));
#endif
}
/**
* egg_screen_exec_environment:
* @screen: A #GdkScreen
*
* Description: Modifies the current program environment to
* ensure that $DISPLAY is set such that a launched application
* inheriting this environment would appear on @screen.
*
* Returns: a newly-allocated %NULL-terminated array of strings or
* %NULL on error. Use g_strfreev() to free it.
**/
char **
egg_screen_exec_environment (GdkScreen *screen)
{
char **retval = NULL;
int i;
#ifdef HAVE_GTK_MULTIHEAD
int display_index = -1;
g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
for (i = 0; environ [i]; i++)
if (!strncmp (environ [i], "DISPLAY", 7))
display_index = i;
if (display_index == -1)
display_index = i++;
#else
for (i = 0; environ [i]; i++);
#endif
retval = g_new (char *, i + 1);
for (i = 0; environ [i]; i++)
#ifdef HAVE_GTK_MULTIHEAD
if (i == display_index)
retval [i] = egg_screen_exec_display_string (screen);
else
#endif
retval [i] = g_strdup (environ [i]);
retval [i] = NULL;
return retval;
}
/**
* egg_screen_execute_async:
* @screen: A #GdkScreen
* @dir: Directory in which child should be executed, or %NULL for current
* directory
* @argc: Number of arguments
* @argv: Argument vector to exec child
*
* Description: Like gnome_execute_async(), but ensures that the child
* is launched in an environment such that if it calls XOpenDisplay()
* the resulting display would have @screen as the default screen.
*
* Returns: process id of child, or %-1 on error.
**/
int
egg_screen_execute_async (GdkScreen *screen,
const char *dir,
int argc,
char * const argv [])
{
#ifdef HAVE_GTK_MULTIHEAD
char **envp = NULL;
int envc = 0;
int retval;
g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
if (gdk_screen_get_default () != screen) {
envc = 1;
envp = g_new0 (char *, 2);
envp [0] = egg_screen_exec_display_string (screen);
}
retval = gnome_execute_async_with_env (dir, argc, argv, envc, envp);
g_strfreev (envp);
return retval;
#else
return gnome_execute_async (dir, argc, argv);
#endif
}
/**
* egg_screen_execute_shell:
* @screen: A #GdkScreen.
* @dir: Directory in which child should be executed, or %NULL for current
* directory
* @commandline: Shell command to execute
*
* Description: Like gnome_execute_shell(), but ensures that the child
* is launched in an environment such that if it calls XOpenDisplay()
* the resulting display would have @screen as the default screen.
*
* Returns: process id of shell, or %-1 on error.
**/
int
egg_screen_execute_shell (GdkScreen *screen,
const char *dir,
const char *command)
{
#ifdef HAVE_GTK_MULTIHEAD
int retval = -1;
g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
if (gdk_screen_get_default () == screen)
retval = gnome_execute_shell (dir, command);
else {
char *exec;
char *display;
display = egg_screen_exec_display_string (screen);
exec = g_strconcat (display, " ", command, NULL);
retval = gnome_execute_shell (dir, exec);
g_free (display);
g_free (exec);
}
return retval;
#else
return gnome_execute_shell (dir, command);
#endif
}
/**
* egg_screen_execute_command_line_async:
* @screen: A #GdkScreen.
* @command_line: a command line
* @error: return location for errors
*
* Description: Like g_spawn_command_line_async(), but ensures that
* the child is launched in an environment such that if it calls
* XOpenDisplay() the resulting display would have @screen as the
* default screen.
*
* Returns: %TRUE on success, %FALSE if error is set.
**/
gboolean
egg_screen_execute_command_line_async (GdkScreen *screen,
const char *command,
GError **error)
{
#ifdef HAVE_GTK_MULTIHEAD
gboolean retval;
char **argv = NULL;
char **envp = NULL;
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
g_return_val_if_fail (command != NULL, FALSE);
if (!g_shell_parse_argv (command, NULL, &argv, error))
return FALSE;
if (gdk_screen_get_default () != screen)
envp = egg_screen_exec_environment (screen);
retval = g_spawn_async (g_get_home_dir (),
argv, envp, G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, error);
g_strfreev (argv);
g_strfreev (envp);
return retval;
#else
return g_spawn_command_line_async (command, error);
#endif
}
syntax highlighted by Code2HTML, v. 0.9.1