r470 - trunk
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Fri Jan 25 05:43:02 EST 2008
Author: icculus
Date: 2008-01-25 05:42:56 -0500 (Fri, 25 Jan 2008)
New Revision: 470
Modified:
trunk/platform_unix.c
Log:
First completely untested shot at Unix browser launch. So, so nasty.
Modified: trunk/platform_unix.c
===================================================================
--- trunk/platform_unix.c 2008-01-25 08:13:13 UTC (rev 469)
+++ trunk/platform_unix.c 2008-01-25 10:42:56 UTC (rev 470)
@@ -932,6 +932,216 @@
} // MojoPlatform_dlclose
+#if !PLATFORM_MACOSX && !PLATFORM_BEOS
+typedef enum
+{
+ DESKTOP_MUST_CHECK,
+ DESKTOP_UNKNOWN,
+ DESKTOP_GNOME,
+ DESKTOP_KDE,
+ DESKTOP_XFCE4,
+} UnixDesktopType;
+
+
+static UnixDesktopType getDesktopType(void)
+{
+ static UnixDesktopType retval = DESKTOP_MUST_CHECK;
+ if (retval == DESKTOP_MUST_CHECK)
+ {
+ const char *envr = getenv("KDE_FULL_SESSION");
+ if ( (envr != NULL) && (strcmp(envr, "true") == 0) )
+ retval = DESKTOP_KDE;
+ else if (getenv("GNOME_DESKTOP_SESSION_ID") != NULL)
+ retval = DESKTOP_GNOME;
+ else if (system("xprop -root _DT_SAVE_MODE |"
+ " grep ' = \"xfce4\"$' >/dev/null 2>&1") == 0)
+ {
+ retval = DESKTOP_XFCE4; // this nasty compliments of xdg-open.
+ } // else if
+ else
+ {
+ retval = DESKTOP_UNKNOWN;
+ } // else
+ } // if
+
+ return retval;
+} // getDesktopType
+
+
+static char *shellEscape(const char *str)
+{
+ size_t len = 0;
+ char *retval = NULL;
+ const char *ptr = NULL;
+ char *dst = NULL;
+
+ for (ptr = str; *ptr; ptr++)
+ len += (*ptr == '\'') ? 4 : 1;
+
+ retval = (char *) xmalloc(len + 3); // +2 single quotes and a null char.
+ dst = retval;
+ *(dst++) = '\'';
+
+ for (ptr = str; *ptr; ptr++)
+ {
+ const char ch = *ptr;
+ if (ch != '\'')
+ *(dst++) = ch;
+ else
+ {
+ *(dst++) = '\'';
+ *(dst++) = '\\';
+ *(dst++) = '\'';
+ *(dst++) = '\'';
+ } // else
+ } // for
+
+ *(dst++) = '\'';
+ *(dst++) = '\0';
+ return retval;
+} // shellEscape
+
+
+static char **splitString(const char *str, const char sep)
+{
+ char **retval = NULL;
+ int count = 0;
+ const char *lastptr = NULL;
+ const char *ptr = NULL;
+ for (ptr = str; *ptr; ptr++)
+ {
+ if (*ptr == sep)
+ count++;
+ } // for
+
+ retval = (char **) xmalloc(sizeof (char *) * (count + 1));
+ for (lastptr = ptr = str; *ptr; ptr++)
+ {
+ if (*ptr == sep)
+ {
+ const size_t len = (size_t) (ptr - lastptr);
+ if (len > 0)
+ {
+ retval[count] = (char *) xmalloc(len + 1);
+ memcpy(retval[count], lastptr, len);
+ retval[count][len] = '\0';
+ count++;
+ } // if
+ lastptr = ptr + 1;
+ } // if
+ } // for
+
+ retval[count] = NULL;
+ return retval;
+} // splitString
+
+
+static const char *defaultBrowsers(void)
+{
+ const boolean ttyonly = ( (GGui == NULL) ||
+ (strcmp(GGui->name(), "stdio") == 0) ||
+ (strcmp(GGui->name(), "ncurses") == 0) );
+
+ return ((ttyonly) ? "links:lynx" : "firefox:mozilla:netscape");
+} // defaultBrowsers
+
+
+static boolean launchGenericBrowser(const char *escapedurl)
+{
+ // See http://catb.org/~esr/BROWSER/ for details.
+ // !!! FIXME: this isn't actually entirely right...we're not parsing
+ // !!! FIXME: out %s sequences or anything...the spec seems to think
+ // !!! FIXME: we should either parse the commands into an execv() array
+ // !!! FIXME: ourselves, duplicating the shell's parser exactly, or
+ // !!! FIXME: just pass them unmolested to system(), and hope that
+ // !!! FIXME: the url is escaped correctly since no one is declared to
+ // !!! FIXME: be in charge of that.
+ // !!! FIXME: esr probably shouldn't have done the %s thing, and just
+ // !!! FIXME: said "plug the url on as argv[1] and be done with it,
+ // !!! FIXME: if they need fancy scripting, let them write a script file."
+ // !!! FIXME: Also, it doesn't talk about if you should block, or fork(),
+ // !!! FIXME: but it looks like blocking is the only reasonable thing.
+ // !!! FIXME: ...soooo, that's what I'm doing here. Sorry, Eric. :/
+ boolean retval = false;
+ const char *defenvr = defaultBrowsers();
+ const char *_envr = getenv("BROWSER");
+ char *envr = xstrdup(_envr ? _envr : defenvr);
+ char *ptr = envr;
+ char *prev = envr;
+ char *cmd = NULL;
+
+ while (1)
+ {
+ const char ch = *ptr;
+ const boolean lastone = (ch == '\0');
+ if ((ch == ':') || (lastone))
+ {
+ *ptr = '\0';
+ if (ptr != prev)
+ {
+ cmd = format("%0 %1", prev, escapedurl);
+ retval = (system(cmd) == 0);
+ free(cmd);
+ if (retval)
+ break;
+ } // if
+ prev = ptr++;
+ } // if
+
+ if (lastone)
+ break;
+
+ ptr++;
+ } // for
+
+ free(envr);
+ return retval;
+} // launchGenericBrowser
+
+
+static boolean unix_launchBrowser(const char *url)
+{
+ boolean retval = false;
+ char *escapedurl = shellEscape(url);
+ char *cmd = format("xdg-utils %0", escapedurl);
+ int rc = system(cmd);
+ free(cmd);
+
+ if (rc != 0)
+ {
+ // no xdg-open in the $PATH, or it failed. Try to do it ourselves...
+ const UnixDesktopType desktop = getDesktopType();
+ if (desktop == DESKTOP_KDE)
+ cmd = format("kfmclient exec %0", escapedurl);
+ else if (desktop == DESKTOP_GNOME)
+ cmd = format("gnome-open %0", escapedurl);
+ else if (desktop == DESKTOP_XFCE4)
+ cmd = format("exo-open %0", escapedurl);
+ else // (desktop == DESKTOP_UNKNOWN) or we missed something here.
+ {
+ cmd = NULL;
+ retval = launchGenericBrowser(escapedurl);
+ } // else
+
+ if (cmd != NULL)
+ {
+ retval = (system(cmd) == 0);
+ free(cmd);
+
+ // !!! FIXME: apparently you can't trust the return value from
+ // !!! FIXME: KDE <= 3.5.4, so for now we just always ignore
+ // !!! FIXME: it and pretend it worked out.
+ if (desktop == DESKTOP_KDE)
+ retval = true;
+ } // if
+ } // if
+
+ free(escapedurl);
+ return retval;
+} // unix_launchBrowser
+#endif
+
+
boolean MojoPlatform_launchBrowser(const char *url)
{
#if PLATFORM_MACOSX
@@ -944,7 +1154,7 @@
extern int beos_launchBrowser(const char *url);
return beos_launchBrowser(url) ? true : false;
#else
- return false; // !!! FIXME: write me.
+ return unix_launchBrowser(url);
#endif
} // MojoPlatform_launchBrowser
More information about the mojosetup-commits
mailing list