r474 - in trunk: . examples/duke3d meta meta/xdg-utils
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Fri Jan 25 11:01:23 EST 2008
Author: icculus
Date: 2008-01-25 11:01:19 -0500 (Fri, 25 Jan 2008)
New Revision: 474
Added:
trunk/meta/
trunk/meta/xdg-utils/
trunk/meta/xdg-utils/xdg-open
Modified:
trunk/examples/duke3d/make.sh
trunk/mojosetup.c
trunk/platform_unix.c
Log:
Screw it, just run a shipped copy of xdg-open if the system doesn't have it.
Modified: trunk/examples/duke3d/make.sh
===================================================================
--- trunk/examples/duke3d/make.sh 2008-01-25 11:09:16 UTC (rev 473)
+++ trunk/examples/duke3d/make.sh 2008-01-25 16:01:19 UTC (rev 474)
@@ -103,6 +103,12 @@
cp data/* image/data/
cp meta/* image/meta/
+# Need these scripts to do things like install menu items, etc, on Unix.
+if [ "$OSTYPE" = "Linux" ]; then
+ mkdir image/meta/xdg-utils
+ cp -av ../../meta/xdg-utils/* image/meta/xdg-utils/
+fi
+
# Make a .zip archive of the Base Archive dirs and nuke the originals...
cd image
zip -9r ../pdata.zip *
Added: trunk/meta/xdg-utils/xdg-open
===================================================================
--- trunk/meta/xdg-utils/xdg-open (rev 0)
+++ trunk/meta/xdg-utils/xdg-open 2008-01-25 16:01:19 UTC (rev 474)
@@ -0,0 +1,436 @@
+#!/bin/sh
+#---------------------------------------------
+# xdg-open
+#
+# Utility script to open a URL in the registered default application.
+#
+# Refer to the usage() function below for usage.
+#
+# Copyright 2006, Kevin Krammer <kevin.krammer at gmx.at>
+# Copyright 2006, Jeremy White <jwhite at codeweavers.com>
+#
+# LICENSE:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#---------------------------------------------
+
+manualpage()
+{
+cat << _MANUALPAGE
+Name
+
+xdg-open - opens a file or URL in the user's preferred application
+
+Synopsis
+
+xdg-open { file | URL }
+
+xdg-open { --help | --manual | --version }
+
+Description
+
+xdg-open opens a file or URL in the user's preferred application. If a URL is
+provided the URL will be opened in the user's preferred web browser. If a file
+is provided the file will be opened in the preferred application for files of
+that type. xdg-open supports file, ftp, http and https URLs.
+
+xdg-open is for use inside a desktop session only. It is not recommended to use
+xdg-open as root.
+
+Options
+
+--help
+ Show command synopsis.
+--manual
+ Show this manualpage.
+--version
+ Show the xdg-utils version information.
+
+Exit Codes
+
+An exit code of 0 indicates success while a non-zero exit code indicates
+failure. The following failure codes can be returned:
+
+1
+ Error in command line syntax.
+2
+ One of the files passed on the command line did not exist.
+3
+ A required tool could not be found.
+4
+ The action failed.
+
+Examples
+
+xdg-open 'http://www.freedesktop.org/'
+
+Opens the Freedesktop.org website in the user's default browser
+
+xdg-open /tmp/foobar.png
+
+Opens the PNG image file /tmp/foobar.png in the user's default image viewing
+application.
+
+_MANUALPAGE
+}
+
+usage()
+{
+cat << _USAGE
+xdg-open - opens a file or URL in the user's preferred application
+
+Synopsis
+
+xdg-open { file | URL }
+
+xdg-open { --help | --manual | --version }
+
+_USAGE
+}
+
+#@xdg-utils-common@
+
+#----------------------------------------------------------------------------
+# Common utility functions included in all XDG wrapper scripts
+#----------------------------------------------------------------------------
+
+DEBUG()
+{
+ [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
+ [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
+ shift
+ echo "$@" >&2
+}
+
+#-------------------------------------------------------------
+# Exit script on successfully completing the desired operation
+
+exit_success()
+{
+ if [ $# -gt 0 ]; then
+ echo "$@"
+ echo
+ fi
+
+ exit 0
+}
+
+
+#-----------------------------------------
+# Exit script on malformed arguments, not enough arguments
+# or missing required option.
+# prints usage information
+
+exit_failure_syntax()
+{
+ if [ $# -gt 0 ]; then
+ echo "xdg-open: $@" >&2
+ echo "Try 'xdg-open --help' for more information." >&2
+ else
+ usage
+ echo "Use 'man xdg-open' or 'xdg-open --manual' for additional info."
+ fi
+
+ exit 1
+}
+
+#-------------------------------------------------------------
+# Exit script on missing file specified on command line
+
+exit_failure_file_missing()
+{
+ if [ $# -gt 0 ]; then
+ echo "xdg-open: $@" >&2
+ fi
+
+ exit 2
+}
+
+#-------------------------------------------------------------
+# Exit script on failure to locate necessary tool applications
+
+exit_failure_operation_impossible()
+{
+ if [ $# -gt 0 ]; then
+ echo "xdg-open: $@" >&2
+ fi
+
+ exit 3
+}
+
+#-------------------------------------------------------------
+# Exit script on failure returned by a tool application
+
+exit_failure_operation_failed()
+{
+ if [ $# -gt 0 ]; then
+ echo "xdg-open: $@" >&2
+ fi
+
+ exit 4
+}
+
+#------------------------------------------------------------
+# Exit script on insufficient permission to read a specified file
+
+exit_failure_file_permission_read()
+{
+ if [ $# -gt 0 ]; then
+ echo "xdg-open: $@" >&2
+ fi
+
+ exit 5
+}
+
+#------------------------------------------------------------
+# Exit script on insufficient permission to read a specified file
+
+exit_failure_file_permission_write()
+{
+ if [ $# -gt 0 ]; then
+ echo "xdg-open: $@" >&2
+ fi
+
+ exit 6
+}
+
+check_input_file()
+{
+ if [ ! -e "$1" ]; then
+ exit_failure_file_missing "file '$1' does not exist"
+ fi
+ if [ ! -r "$1" ]; then
+ exit_failure_file_permission_read "no permission to read file '$1'"
+ fi
+}
+
+check_vendor_prefix()
+{
+ file_label="$2"
+ [ -n "$file_label" ] || file_label="filename"
+ file=`basename "$1"`
+ case "$file" in
+ [a-zA-Z]*-*)
+ return
+ ;;
+ esac
+
+ echo "xdg-open: $file_label '$file' does not have a proper vendor prefix" >&2
+ echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
+ echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
+ echo "Use --novendor to override or 'xdg-open --manual' for additional info." >&2
+ exit 1
+}
+
+check_output_file()
+{
+ # if the file exists, check if it is writeable
+ # if it does not exists, check if we are allowed to write on the directory
+ if [ -e "$1" ]; then
+ if [ ! -w "$1" ]; then
+ exit_failure_file_permission_write "no permission to write to file '$1'"
+ fi
+ else
+ DIR=`dirname "$1"`
+ if [ ! -w "$DIR" -o ! -x "$DIR" ]; then
+ exit_failure_file_permission_write "no permission to create file '$1'"
+ fi
+ fi
+}
+
+#----------------------------------------
+# Checks for shared commands, e.g. --help
+
+check_common_commands()
+{
+ while [ $# -gt 0 ] ; do
+ parm="$1"
+ shift
+
+ case "$parm" in
+ --help)
+ usage
+ echo "Use 'man xdg-open' or 'xdg-open --manual' for additional info."
+ exit_success
+ ;;
+
+ --manual)
+ manualpage
+ exit_success
+ ;;
+
+ --version)
+ echo "xdg-open 1.0.1"
+ exit_success
+ ;;
+ esac
+ done
+}
+
+check_common_commands "$@"
+
+[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
+if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
+ # Be silent
+ xdg_redirect_output=" > /dev/null 2> /dev/null"
+else
+ # All output to stderr
+ xdg_redirect_output=" >&2"
+fi
+
+#--------------------------------------
+# Checks for known desktop environments
+# set variable DE to the desktop environments name, lowercase
+
+detectDE()
+{
+ if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
+ elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
+ elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
+ fi
+}
+
+#----------------------------------------------------------------------------
+# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
+# It also always returns 1 in KDE 3.4 and earlier
+# Simply return 0 in such case
+
+kfmclient_fix_exit_code()
+{
+ version=`kde-config --version 2>/dev/null | grep KDE`
+ major=`echo $version | sed 's/KDE: \([0-9]\).*/\1/'`
+ minor=`echo $version | sed 's/KDE: [0-9]*\.\([0-9]\).*/\1/'`
+ release=`echo $version | sed 's/KDE: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
+ test "$major" -gt 3 && return $1
+ test "$minor" -gt 5 && return $1
+ test "$release" -gt 4 && return $1
+ return 0
+}
+
+open_kde()
+{
+ kfmclient exec "$1"
+ kfmclient_fix_exit_code $?
+
+ if [ $? -eq 0 ]; then
+ exit_success
+ else
+ exit_failure_operation_failed
+ fi
+}
+
+open_gnome()
+{
+ gnome-open "$1"
+
+ if [ $? -eq 0 ]; then
+ exit_success
+ else
+ exit_failure_operation_failed
+ fi
+}
+
+open_xfce()
+{
+ exo-open "$1"
+
+ if [ $? -eq 0 ]; then
+ exit_success
+ else
+ exit_failure_operation_failed
+ fi
+}
+
+open_generic()
+{
+ IFS=":"
+ for browser in $BROWSER; do
+ if [ x"$browser" != x"" ]; then
+
+ browser_with_arg=`echo "$browser" | sed s#%s#"$1"#`
+
+ if [ x"$browser_with_arg" = x"$browser" ]; then "$browser" "$1";
+ else $browser_with_arg;
+ fi
+
+ if [ $? -eq 0 ]; then exit_success;
+ fi
+ fi
+ done
+
+ exit_failure_operation_impossible "no method available for opening '$1'"
+}
+
+[ x"$1" != x"" ] || exit_failure_syntax
+
+url=
+while [ $# -gt 0 ] ; do
+ parm="$1"
+ shift
+
+ case "$parm" in
+ -*)
+ exit_failure_syntax "unexpected option '$parm'"
+ ;;
+
+ *)
+ if [ -n "$url" ] ; then
+ exit_failure_syntax "unexpected argument '$parm'"
+ fi
+ url="$parm"
+ ;;
+ esac
+done
+
+if [ -z "${url}" ] ; then
+ exit_failure_syntax "file or URL argument missing"
+fi
+
+detectDE
+
+if [ x"$DE" = x"" ]; then
+ # if BROWSER variable is not set, check some well known browsers instead
+ if [ x"$BROWSER" = x"" ]; then
+ BROWSER=firefox:mozilla:netscape
+ fi
+ DE=generic
+fi
+
+case "$DE" in
+ kde)
+ open_kde "$url"
+ ;;
+
+ gnome)
+ open_gnome "$url"
+ ;;
+
+ xfce)
+ open_xfce "$url"
+ ;;
+
+ generic)
+ open_generic "$url"
+ ;;
+
+ *)
+ exit_failure_operation_impossible "no method available for opening '$url'"
+ ;;
+esac
Property changes on: trunk/meta/xdg-utils/xdg-open
___________________________________________________________________
Name: svn:executable
+ *
Modified: trunk/mojosetup.c
===================================================================
--- trunk/mojosetup.c 2008-01-25 11:09:16 UTC (rev 473)
+++ trunk/mojosetup.c 2008-01-25 16:01:19 UTC (rev 474)
@@ -749,12 +749,18 @@
int MojoSetup_testLaunchBrowserCode(int argc, char **argv)
{
int i;
+
+ if (!MojoArchive_initBaseArchive()) // Maybe need for xdg-open script.
+ panic("Initial setup failed. Cannot continue.");
+
printf("Testing browser launching code...\n\n");
for (i = 1; i < argc; i++)
{
const boolean rc = MojoPlatform_launchBrowser(argv[i]);
printf("Launch '%s': %s\n", argv[i], rc ? "success" : "failure");
} // for
+
+ MojoArchive_deinitBaseArchive();
return 0;
} // MojoSetup_testLaunchBrowserCode
#endif
Modified: trunk/platform_unix.c
===================================================================
--- trunk/platform_unix.c 2008-01-25 11:09:16 UTC (rev 473)
+++ trunk/platform_unix.c 2008-01-25 16:01:19 UTC (rev 474)
@@ -26,6 +26,7 @@
#include <syslog.h>
#include <dirent.h>
#include <fcntl.h>
+#include <wait.h>
#if MOJOSETUP_HAVE_SYS_UCRED_H
# ifdef MOJOSETUP_HAVE_MNTENT_H
@@ -55,6 +56,7 @@
#include "platform.h"
#include "gui.h"
+#include "fileio.h"
static struct timeval startup_time;
@@ -933,39 +935,98 @@
#if !PLATFORM_MACOSX && !PLATFORM_BEOS
-typedef enum
+static int runScriptString(const char *str, boolean devnull, const char **_argv)
{
- DESKTOP_MUST_CHECK,
- DESKTOP_UNKNOWN,
- DESKTOP_GNOME,
- DESKTOP_KDE,
- DESKTOP_XFCE4,
-} UnixDesktopType;
+ int retval = 127;
+ pid_t pid = 0;
+ int pipes[2];
+ if (pipe(pipes) == -1)
+ return retval;
-static UnixDesktopType getDesktopType(void)
-{
- static UnixDesktopType retval = DESKTOP_MUST_CHECK;
- if (retval == DESKTOP_MUST_CHECK)
+ pid = fork();
+ if (pid == -1) // -1 == fork() failed.
{
- 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)
+ close(pipes[0]);
+ close(pipes[1]);
+ return retval;
+ } // if
+
+ else if (pid == 0) // we're the child process.
+ {
+ int argc = 0;
+ const char **argv = NULL;
+
+ close(pipes[1]); // close the writing end.
+ dup2(pipes[0], 0); // replace stdin.
+ if (devnull)
{
- retval = DESKTOP_XFCE4; // this nasty compliments of xdg-open.
- } // else if
- else
+ dup2(open("/dev/null", O_WRONLY), 1); // replace stdout
+ dup2(open("/dev/null", O_WRONLY), 2); // replace stderr
+ } // if
+
+ while (_argv[argc++] != NULL) { /* no-op */ }
+ argv = (const char **) xmalloc(sizeof (char *) * argc+3);
+ argv[0] = "/bin/sh";
+ argv[1] = "-s";
+ for (argc = 0; _argv[argc] != NULL; argc++)
+ argv[argc+2] = _argv[argc];
+ argv[argc+2] = NULL;
+
+ execv(argv[0], (char **) argv);
+ _exit(retval); // uhoh, failed.
+ } // else if
+
+ else // we're the parent (pid == child process id).
+ {
+ int status = 0;
+ size_t len = strlen(str);
+ boolean failed = false;
+ close(pipes[0]); // close the reading end.
+ failed |= (write(pipes[1], str, len) != len);
+ failed |= (close(pipes[1]) == -1);
+
+ // !!! FIXME: we need a GGui->pump() or something here if we'll block.
+ if (waitpid(pid, &status, 0) != -1)
{
- retval = DESKTOP_UNKNOWN;
- } // else
+ if (WIFEXITED(status))
+ retval = WEXITSTATUS(status);
+ } // if
+ } // else
+
+ return retval;
+} // runScriptString
+
+
+static int runScript(const char *script, boolean devnull, const char **argv)
+{
+ int retval = 127;
+ char *str = NULL;
+ MojoInput *in = MojoInput_newFromArchivePath(GBaseArchive, script);
+ if (in != NULL)
+ {
+ int64 len = in->length(in);
+ if (len > 0)
+ {
+ str = (char *) xmalloc(len + 1);
+ if (in->read(in, str, len) == len)
+ str[len] = '\0';
+ else
+ {
+ free(str);
+ str = NULL;
+ } // else
+ } // if
+
+ in->close(in);
} // if
+ if (str != NULL)
+ retval = runScriptString(str, devnull, argv);
+
+ free(str);
return retval;
-} // getDesktopType
+} // runScript
static char *shellEscape(const char *str)
@@ -1002,108 +1063,27 @@
} // shellEscape
-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 -raise: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-open %0 >/dev/null 2>&1", escapedurl);
+ char *path = findBinaryInPath("dfdfxdg-open");
- retval = (system(cmd) == 0);
- free(cmd);
-
- if (!retval)
+ if (path != NULL) // it's installed on the system; use that.
{
- // 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 >/dev/null 2>&1", escapedurl);
- else if (desktop == DESKTOP_GNOME)
- cmd = format("gnome-open %0 >/dev/null 2>&1", escapedurl);
- else if (desktop == DESKTOP_XFCE4)
- cmd = format("exo-open %0 >/dev/null 2>&1", escapedurl);
- else // (desktop == DESKTOP_UNKNOWN) or we missed something here.
- {
- cmd = NULL;
- retval = launchGenericBrowser(escapedurl);
- } // else
+ char *escapedurl = shellEscape(url);
+ char *cmd = format("xdg-open %0 >/dev/null 2>&1", escapedurl);
+ retval = (system(cmd) == 0);
+ free(cmd);
+ free(escapedurl);
+ free(path);
+ } // if
- 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
+ else // try our fallback copy of xdg-utils in GBaseArchive?
+ {
+ const char *argv[] = { url, NULL };
+ retval = (runScript("meta/xdg-utils/xdg-open", true, argv) == 0);
} // if
- free(escapedurl);
return retval;
} // unix_launchBrowser
#endif
More information about the mojosetup-commits
mailing list