1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/*
* Copyright (C) 1999-2003, 2007 Red Hat, Inc. All rights reserved.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "config.h"
#include <sys/types.h>
#include <fcntl.h>
#include <libintl.h>
#include <locale.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef DISABLE_X11
#include <gtk/gtk.h>
#endif
#include "userhelper.h"
#include "userhelper-wrap.h"
#ifdef DEBUG_CONSOLEHELPER
#define debug_msg(...) g_print(__VA_ARGS__)
#else
#define debug_msg(...) ((void)0)
#endif
int
main(int argc, char *argv[])
{
char **constructed_argv, **sanitized_argv;
int offset, i;
char *progname;
/* volatile here suppress warnings about unused local variable */
volatile gboolean graphics_available = FALSE;
#ifndef DISABLE_X11
char *display;
#endif
/* g_strdupv suppresses tainted string warnings */
if ((sanitized_argv = g_strdupv(argv)) == NULL) {
debug_msg("g_strdupv(argv) == NULL\n");
return 1;
}
#ifdef DISABLE_X11
/* We're in the non-X11 version. If we have the X11-capable version
* installed, try to let it worry about all of this. */
if (execv(UH_CONSOLEHELPER_X11_PATH, sanitized_argv) < 0)
debug_msg("execv(%s, ...) < 0\n", UH_CONSOLEHELPER_X11_PATH);
#endif
/* Set up locales. */
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
bind_textdomain_codeset(PACKAGE, "UTF-8");
textdomain(PACKAGE);
/* Find the basename of the program we were invoked as. */
progname = strrchr(sanitized_argv[0], '/');
if(progname) {
progname++; /* Skip over the '/' character. */
} else {
progname = sanitized_argv[0];
}
#ifndef DISABLE_X11
/* If DISPLAY is set, or if stdin isn't a TTY, we have to check if we
* can display in a window. Otherwise, all is probably lost. */
/* g_strdup suppresses tainted string warnings */
display = g_strdup(getenv("DISPLAY"));
if (((display != NULL) && (strlen(display) > 0)) ||
!isatty(STDIN_FILENO)) {
int fake_argc, stderrfd, fd;
char **fake_argv;
#ifdef USE_STARTUP_NOTIFICATION
/* GTK+ clears the environment variable at init-time, which
* simply won't do. */
char *sn_id = NULL;
sn_id = g_strdup(getenv("DESKTOP_STARTUP_ID"));
#endif
fake_argc = 1;
fake_argv = g_malloc0_n(fake_argc + 1, sizeof(*fake_argv));
if (fake_argv != NULL)
fake_argv[0] = sanitized_argv[0];
/* Redirect stderr to silence Xlib's "can't open display"
* warning, which we don't mind. */
stderrfd = dup(STDERR_FILENO);
if (stderrfd != -1) {
close(STDERR_FILENO);
do {
fd = open("/dev/null", O_WRONLY | O_APPEND);
} while((fd != -1) && (fd != STDERR_FILENO));
}
if (fake_argv != NULL && gtk_init_check(&fake_argc, &fake_argv))
graphics_available = TRUE;
g_free(fake_argv);
/* Restore stderr. */
if (stderrfd != -1) {
dup2(stderrfd, STDERR_FILENO);
close(stderrfd);
}
#ifdef USE_STARTUP_NOTIFICATION
/* Restore DESKTOP_STARTUP_ID. I'll think up something mean
* to say about having to do this eventually. */
if (sn_id != NULL)
setenv("DESKTOP_STARTUP_ID", sn_id, 1);
g_free(sn_id);
#endif
}
g_free(display);
#endif
/* Allocate space for a new argv array, with room for up to 3 more
* items than we have in argv, plus the NULL-terminator. */
constructed_argv = g_malloc0_n(argc + 3 + 1, sizeof(char *));
if (graphics_available) {
/* Set up args to tell userhelper to wrap the named program
* using a consolehelper window to interact with the user. */
constructed_argv[0] = (char *)UH_PATH;
constructed_argv[1] = (char *)UH_WRAP_OPT;
constructed_argv[2] = progname;
offset = 2;
} else {
/* Set up args to tell userhelper to wrap the named program
* using a text-only interface. */
constructed_argv[0] = (char *)UH_PATH;
constructed_argv[1] = (char *)UH_TEXT_OPT;
constructed_argv[2] = (char *)UH_WRAP_OPT;
constructed_argv[3] = progname;
offset = 3;
}
/* Copy the command-line arguments, except for the program name. */
for (i = 1; i < argc; i++) {
constructed_argv[i + offset] = sanitized_argv[i];
}
/* If we can open a window, use the graphical wrapper routine. */
#ifndef DISABLE_X11
if (graphics_available) {
int r = userhelper_runv(FALSE, UH_PATH, constructed_argv);
g_free(constructed_argv);
g_strfreev(sanitized_argv);
return r;
}
#endif
/* Text mode doesn't need the whole pipe thing. */
if (execv(UH_PATH, constructed_argv) < 0) {
debug_msg("execv(%s, ...) < 0\n", UH_PATH);
g_free(constructed_argv);
g_strfreev(sanitized_argv);
return 1;
}
g_free(constructed_argv);
g_strfreev(sanitized_argv);
return 0;
}
|