#!/bin/bash # # Copyright 1999-2004 Gentoo Technologies, Inc. # Distributed under the terms of the GNU General Public License v2 # $Header: /var/cvsroot/gentoo-src/mozilla-launcher/mozilla-launcher,v 1.21 2004/09/29 03:13:04 agriffis Exp $ # Set MOZILLA_NEWTYPE to "window" in your environment if you prefer # new windows instead of new tabs newtype=${MOZILLA_NEWTYPE:-"window"} # Make sure necessary progs are in the PATH PATH=/usr/bin:/bin:/usr/X11R6/bin:$PATH main() { local args mozargs urls u i local candidates retval=0 remote_supports_dash_a progname local zero=${0##*/} # Determine if we're called as firefox or mozilla and set up # variables appropriately which_browser || exit 1 # note: modifies $zero # Parse the command-line and set args, mozargs and urls parse_cmdline "$@" || exit 1 # Make sure we'll get at least an empty window/tab # when nothing else is specified on the cmdline. if [[ $# -eq 0 ]]; then if [[ $zero == thunderbird* ]]; then mozargs=-mail else urls=('') fi fi # Set the candidates array with find_running find_running # Handle some special args. We want to handle these ourselves so # that we can find the right window on the screen to target. set -- "${mozargs[@]}" while [[ $# -gt 0 ]]; do case $1 in -mail) try_running 'xfeDoCommand(openInbox)' ;; -compose) try_running 'xfeDoCommand(composeMessage)' ;; -remote) try_running "$2" && shift ;; esac [[ $? -eq 0 ]] && { shift; continue; } # Error path: try_running failed, so prepend remaining mozargs to # args and drop through to call the browser binary args=("$@" "${args[@]}") break done # If there's no running browser, or we've got args, start an # instance. if [[ ${#args[@]} -gt 0 ]] || ! try_running 'ping()'; then # Assume the first url should just be tacked on the end. try_start "${args[@]}" ${urls:+"${urls[0]}"} set -- "${urls[@]}"; shift; urls=("$@") # shift off the first url candidates=$DISPLAY args=() # Handle case of multiple URLs by waiting for browser to map to # the screen so that it can be found by $remote below if [[ ${#urls[@]} -gt 0 ]]; then if [[ -x /usr/bin/xtoolwait ]]; then xtoolwait sleep 10 # hope it hasn't mapped yet else sleep 1 for ((i = 0; i < 40; i = i + 1)); do try_running 'ping()' && break || sleep 0.25 done fi fi fi # Handle multiple URLs by looping over the xremote call for u in "${urls[@]}"; do if [[ $u == mailto:* ]]; then try_running "mailto(${u#mailto:})" || retval=$? else try_running "openURL($u,new-$newtype)" || retval=$? fi done # Will only wait here if browser was started by this script if ! wait; then retval=$? echo "${mozbin##*/} exited with non-zero status ($?)" >&2 fi exit $retval } which_browser() { # Support mozilla, mozilla-bin, firefox, firefox-bin, thunderbird, # thunderbird-bin! # This case statement does the setup for source-based browsers and # just drops through for binary-based browsers. case $zero in *fox) export MOZILLA_FIVE_HOME="/usr/lib/MozillaFirefox" remote=$MOZILLA_FIVE_HOME/mozilla-xremote-client mozbin=$MOZILLA_FIVE_HOME/firefox-bin grepfor=Firefox-bin ;; *mozilla) export MOZILLA_FIVE_HOME="/usr/lib/mozilla" remote=$MOZILLA_FIVE_HOME/mozilla-xremote-client mozbin=$MOZILLA_FIVE_HOME/mozilla-bin grepfor=Mozilla-bin ;; *sunbird) export MOZILLA_FIVE_HOME="/usr/lib/MozillaSunbird" remote=$MOZILLA_FIVE_HOME/mozilla-xremote-client mozbin=$MOZILLA_FIVE_HOME/sunbird-bin grepfor=Sunbird-bin ;; *thunderbird) export MOZILLA_FIVE_HOME="/usr/lib/MozillaThunderbird" remote=$MOZILLA_FIVE_HOME/mozilla-xremote-client mozbin=$MOZILLA_FIVE_HOME/thunderbird-bin grepfor=Thunderbird-bin ;; *-bin) unset mozbin # just in case... ;; # but don't do anything yet *) echo "$0: unknown browser" >&2 return 1 ;; esac # Attempt to use -bin version if source version isn't available if [[ -n $mozbin && ! -f $mozbin ]]; then unset mozbin # it's bogus anyway zero=${zero}-bin fi case $zero in *fox-bin) export MOZILLA_FIVE_HOME="/opt/firefox" remote=$MOZILLA_FIVE_HOME/mozilla-xremote-client mozbin=$MOZILLA_FIVE_HOME/firefox-bin grepfor=Firefox-bin ;; *mozilla-bin) export MOZILLA_FIVE_HOME="/opt/mozilla" remote=$MOZILLA_FIVE_HOME/mozilla-xremote-client mozbin=$MOZILLA_FIVE_HOME/mozilla-bin grepfor=Mozilla-bin ;; *sunbird-bin) export MOZILLA_FIVE_HOME="/opt/sunbird" remote=$MOZILLA_FIVE_HOME/mozilla-xremote-client mozbin=$MOZILLA_FIVE_HOME/sunbird-bin grepfor=Sunbird-bin ;; *thunderbird-bin) export MOZILLA_FIVE_HOME="/opt/thunderbird" remote=$MOZILLA_FIVE_HOME/mozilla-xremote-client mozbin=$MOZILLA_FIVE_HOME/thunderbird-bin grepfor=Thunderbird-bin ;; esac # Make sure we got something if [[ -z $mozbin || ! -f $mozbin ]]; then echo "$0: can't find the browser :-(" >&2 return 1 fi # Newer xremote has the ability to specify a target program. Base # this on ${zero} but workaround bug 247754 for thunderbird progname=${zero%-bin} if [[ $progname == thunderbird ]]; then grep -q '"0\.[78]"' ${MOZILLA_FIVE_HOME}/defaults/pref/*.js \ && progname=Thunderbird fi # Set LD_LIBRARY_PATH (also set in /etc/env.d/10*) export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME:$MOZILLA_FIVE_HOME/plugins${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} return 0 } # parse_cmdline: set args, mozargs and urls, which are dynamically # scoped in main() parse_cmdline() { # Validate the args and extract the urls args=() # general arguments mozargs=() # arguments that we handle specifically urls=() # urls to open while [[ $# -ne 0 ]] ; do if [[ $1 == -* ]] ; then case "${1#-}" in height|width|CreateProfile|P|UILocale|contentLocale|edit|chrome) args=("${args[@]}" "$1" "$2") shift 2 ;; mail|compose) mozargs=("${mozargs[@]}" "$1") shift 1 ;; remote) mozargs=("${mozargs[@]}" "$1" "$2") shift 2 ;; *) args=("${args[@]}" "$1") shift 1 ;; esac else if [[ $1 == *://*/* ]]; then urls=("${urls[@]}" "$1") elif [[ $1 == *://* ]]; then # as of mozilla_1.7_rc1 the url checking changed for xremote # calls... now three slashes are required for urls, otherwise we # get the following error from xremote: # Error: Failed to send command: 509 internal error urls=("${urls[@]}" "$1/") elif [[ $1 != *://* && $1 != /* && -e $1 ]]; then # relative path to a file, transform to absolute path urls=("${urls[@]}" "file://$PWD/$1") elif [[ $1 != *:* && $1 == *@* ]]; then # looks like an email address, prefix with mailto: so we can # recognize it later. urls=("${urls[@]}" "mailto:$1") else # no idea what this is! just add it to urls and hope it works urls=("${urls[@]}" "$1") fi shift fi done return 0 } # set_logname: make sure LOGNAME is set set_logname() { : ${LOGNAME:=$USER} : ${LOGNAME:=$(whoami)} export LOGNAME } # fake_user: fake user string on browser windows that should be found # by $remote. This is a hack, but on the other hand, anything other # than patching the xremote source would be a hack. This prevents # xremote from mixing up mozilla and firefox windows. fake_user() { local id retval=1 set_logname # Find browser windows with a _MOZILLA_USER property and fake it for id in $(xwininfo -root -tree | awk -v gf="$grepfor" '$0~gf{print $1}'); do if xprop -notype -id $id | grep -Fqx "_MOZILLA_USER = \"$LOGNAME\""; then xprop -id $id -f _MOZILLA_USER 8s -set _MOZILLA_USER "${zero}-$LOGNAME" retval=0 fi done return $retval } # unfake_user: remove the hackery done by fake_user unfake_user() { local id set_logname # Find browser windows with a fake _MOZILLA_USER and fix it for id in $(xwininfo -root -tree | awk -v gf="$grepfor" '$0~gf{print $1}'); do xprop -notype -id $id | grep -Fqx "_MOZILLA_USER = \"${zero}-$LOGNAME\"" \ && xprop -id $id -f _MOZILLA_USER 8s -set _MOZILLA_USER "$LOGNAME" done } # find_running: sets the candidates array find_running() { local screens s # Try to start in an existing session; check all screens # with priority on the current screen screens=("$DISPLAY" $(xdpyinfo | awk ' /^name of display:/ { disp = substr($NF, 0, match($NF, /\.[^.]*$/)-1) } /^number of screens:/ { for (i = 0; i < $NF; i++) { this = sprintf("%s.%d", disp, i) if (this != ENVIRON["DISPLAY"]) print this } }') ) # We used to check displays with xwininfo here but that isn't # necessary with the advent of fake_user and/or -a programname. # Instead just test for a running program if we're on a local # display. if [[ $DISPLAY != :* ]] || killall -0 ${mozbin##*/} &>/dev/null; then candidates=("${screens[@]}") else candidates=() fi } # try_running: try to use an existing browser to run a command try_running() { local s retval=2 # default == can't find an instance # Check for newer xremote which supports -a programname # which thankfully obviates fake_user if [[ -z $remote_supports_dash_a ]]; then if $remote 2>&1 | grep -Fq '[-a '; then remote_supports_dash_a=true else remote_supports_dash_a=false fi fi # Try mozilla-xremote-client on each candidate screen. # Only use mozilla-xremote-client if we have no other args (which # must be passed to the browser binary). if [[ ${#candidates[@]} > 0 ]]; then if $remote_supports_dash_a || [[ -n $MOZ_FORCE_FAKE_USER || \ ( $candidates == :* && -z $MOZ_NO_FAKE_USER ) ]] then # Attempt to find a target browser using either -a or fake_user for s in "${candidates[@]}"; do if $remote_supports_dash_a; then DISPLAY=$s $remote -a ${progname} "$@" retval=$? elif DISPLAY=$s fake_user; then LOGNAME="${zero}-$LOGNAME" DISPLAY=$s $remote "$@" retval=$? DISPLAY=$s unfake_user fi if [[ $retval -eq 0 ]]; then candidates=("$s") # for future calls return 0 fi done else # fake_user stuff takes prohibitively long on a remote # display, so I guess this has the potential to exhibit the # mozilla/firefox mixups for the 1% of users that are running # both simultaneously from a remote machine. for s in "${candidates[@]}"; do DISPLAY=$s $remote "$@" retval=$? if [[ $retval -eq 0 ]]; then candidates=("$s") # for future calls return 0 fi done fi fi # Might as well do this error interpretation here case $retval in 1) echo "Unable to connect to X server" >&2 ;; 2) echo "No running windows found" >&2 ;; 3) echo "Browser doesn't understand command" >&2 ;; *) echo "Unknown error $retval from mozilla-xremote-client" >&2 ;; esac return $retval } # try_start: attempt to start a browser try_start() { # compreg.dat and/or chrome.rdf will screw things up if it's from an # older version. http://bugs.gentoo.org/show_bug.cgi?id=63999 for f in ~/{.,.mozilla/}${zero%-bin}/*/{compreg.dat,chrome.rdf}; do if [[ -f ${f} && ${f} -ot ${mozbin} ]]; then echo "Removing ${f} leftover from older ${zero%-bin}" rm -f "${f}" fi done $mozbin "$@" & } # Call the main sub, which is defined at the top of this script main "$@" # vim:expandtab sw=2: