| #!/bin/sh | |
| #------------------------------------------------------------------------------ | |
| # Winelauncher | |
| # This shell script attempts to intelligently manage the process | |
| # of launching a program with Wine. It adds some level of | |
| # visual feedback to an end user. | |
| # | |
| # Usage: | |
| # winelauncher [options] "<windows program> [program arguments]" | |
| # | |
| # This script is meant to be installed to /usr/bin/wine, and | |
| # to be used to invoke a Windows executable. | |
| # The options are passed through directly to Wine, and are | |
| # documented in the Wine man page. | |
| # | |
| # Copyright (c) 2000 by Jeremy White for CodeWeavers | |
| # | |
| # This library is free software; you can redistribute it and/or | |
| # modify it under the terms of the GNU Lesser General Public | |
| # License as published by the Free Software Foundation; either | |
| # version 2.1 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 | |
| # Lesser General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU Lesser 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 | |
| #------------------------------------------------------------------------------ | |
| #------------------------------------------------------------------------------ | |
| # Primary configuration area - change this if you installed Wine to | |
| # a different location | |
| #------------------------------------------------------------------------------ | |
| WINEBIN=@bindir@ | |
| WINELIB=@libdir@ | |
| WINESERVER= | |
| WINEDLLPATH=@dlldir@ | |
| #------------------------------------------------------------------------------ | |
| # Establish Color Scheme | |
| #------------------------------------------------------------------------------ | |
| COLOR=' -xrm *.Command.background:darkgrey | |
| -xrm *.Command.foreground:black | |
| -xrm *.Text.background:black | |
| -xrm *.Text.foreground:green | |
| -xrm *.Form.background:grey | |
| -xrm *.Form.foreground:green | |
| -xrm *.foreground:green | |
| -xrm *.background:black' | |
| #------------------------------------------------------------------------------ | |
| # Locate either xmessage or gmessage, if we can. | |
| #------------------------------------------------------------------------------ | |
| type xmessage >/dev/null 2>/dev/null | |
| if [ $? -ne 0 ] ; then | |
| # xmessage not found; make sure the user notices this error | |
| # (GUI users wouldn't even notice if we printed the text on console !) | |
| MSGFILE=/tmp/WINE_CANNOT_FIND_XMESSAGE | |
| cat > $MSGFILE << EOF | |
| Warning: | |
| The Wine launcher is unable to find the xmessage program, | |
| which it needs to properly notify you of Wine execution status | |
| or problems. | |
| This launcher script relies heavily on finding this tool, | |
| and without it, it will behave very poorly. | |
| We strongly recommend that you use your distribution's | |
| software methods to locate xmessage, or alternatively | |
| use your favourite internet search engine to find out | |
| how you are supposed to install xmessage on your system. | |
| EOF | |
| # try to display message file with tons of different X11 editors | |
| # until we find one that's installed and working | |
| for EDITPRG in nedit gedit kedit gvim xemacs; do | |
| type $EDITPRG >/dev/null 2>/dev/null | |
| if [ $? -eq 0 ] ; then | |
| # execute editor and exit if successful | |
| $EDITPRG $MSGFILE && exit | |
| fi | |
| done | |
| # ok, we really give up now, this system is hosed ;-) | |
| cat $MSGFILE | |
| else | |
| XMESSAGE="xmessage $COLOR" | |
| fi | |
| launch_winesetup() | |
| { | |
| which winesetup | |
| if [ $? -eq 0 ] ; then | |
| winesetup | |
| else | |
| if [ -x /opt/wine/bin/winesetup ] ; then | |
| /opt/wine/bin/winesetup | |
| else | |
| $XMESSAGE -title "Error" \ | |
| "Error: Unable to find winesetup in your PATH or in /opt/wine/bin: | |
| I am not able to configure Wine. | |
| If winesetup is being distributed in a separate package | |
| that is not installed yet on your system, then please install this | |
| package. | |
| winesetup can also be downloaded from www.codeweavers.com. | |
| If you choose to not use winesetup for configuration, then | |
| you can find information on how to prepare a Wine config file manually | |
| in the Wine README / README.gz file or in the Wine User Guide." | |
| fi | |
| fi | |
| } | |
| #------------------------------------------------------------------------------ | |
| # We're going to do a lot of fancy footwork below. | |
| # Before we get started, it would be nice to know the argv0 | |
| # of the actual script we're running (and lets remove at least | |
| # one level of symlinking). | |
| #------------------------------------------------------------------------------ | |
| argv0_path=`which $0` | |
| if [ -z $argv0_path ] ; then | |
| argv0_path=$0 | |
| fi | |
| real_name=`find $argv0_path -type l -printf "%l\n"` | |
| if [ ! $real_name ]; then | |
| real_name=$argv0_path | |
| elif [ ! -x $real_name ]; then | |
| real_name=`find $argv0_path -printf "%h\n"`/$real_name | |
| fi | |
| argv0_dir=`find $real_name -printf "%h\n"` | |
| if [ -z $argv0_dir ] ; then | |
| argv0_dir=. | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Okay, now all that junk above was established at configure time. | |
| # However, if this is an RPM install, they may have chosen | |
| # to relocate this installation. If so, that stuff above | |
| # is all broken and we should rejigger it. | |
| #------------------------------------------------------------------------------ | |
| WINE_BIN_NAME=wine.bin | |
| if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then | |
| WINEBIN=`find $argv0_dir -maxdepth 1 -perm +0111 -type f -name "$WINE_BIN_NAME" -printf "%h\n" | head -n 1` | |
| fi | |
| if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then | |
| WINEBIN=`find $argv0_dir/../ -maxdepth 1 -perm +0111 -type f -name "$WINE_BIN_NAME" -printf "%h\n" | head -n 1` | |
| fi | |
| if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then | |
| WINE_BIN_NAME=wine | |
| if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then | |
| WINEBIN=`find $argv0_dir -maxdepth 1 -perm +0111 -type f -name "$WINE_BIN_NAME" -printf "%h\n" | head -n 1` | |
| fi | |
| if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then | |
| WINEBIN=`find $argv0_dir/../ -maxdepth 1 -perm +0111 -type f -name "$WINE_BIN_NAME" -printf "%h\n" | head -n 1` | |
| fi | |
| fi | |
| if [ ! -r $WINELIB/libwine.so ] ; then | |
| WINELIB=`find $argv0_dir -maxdepth 2 -name 'libwine.so' -printf "%h\n" | head -n 1` | |
| fi | |
| if [ ! -r $WINELIB/libwine.so ] ; then | |
| WINELIB=`find $argv0_dir/../ -maxdepth 2 -name 'libwine.so' -printf "%h\n" | head -n 1` | |
| fi | |
| if [ -x $WINEBIN/wineserver ] ; then | |
| WINESERVER=$WINEBIN/wineserver | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Hey, if we built Wine from source, let's add a little extra fun to | |
| # mix it up a bit | |
| #------------------------------------------------------------------------------ | |
| if [ -x $WINEBIN/server/wineserver ] ; then | |
| WINESERVER=$WINEBIN/server/wineserver | |
| fi | |
| if [ -r $WINELIB/dlls/ntdll.dll.so ] ; then | |
| WINEDLLPATH=$WINELIB/dlls | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Okay, set the paths and move on. | |
| #------------------------------------------------------------------------------ | |
| export LD_LIBRARY_PATH=$WINELIB:$LD_LIBRARY_PATH | |
| export PATH=$WINEBIN:$PATH | |
| export WINELOADER=$WINEBIN/$WINE_BIN_NAME | |
| export WINEDLLPATH | |
| export WINESERVER | |
| info_flag=~/.wine/.no_prelaunch_window_flag | |
| debug_flag=~/.wine/.no_debug_window_flag | |
| debug_options="warn+all" | |
| if [ -f $info_flag ] ; then | |
| use_info_message=0 | |
| else | |
| use_info_message=1 | |
| fi | |
| if [ -f $debug_flag ] ; then | |
| use_debug_message=0 | |
| else | |
| use_debug_message=1 | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Handle winelib apps going through here | |
| #------------------------------------------------------------------------------ | |
| winelib=0 | |
| if [ -f $argv0_path.so ] ; then | |
| winelib=1 | |
| export WINEPRELOAD=$argv0_path.so | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # No arguments? Help 'em out | |
| #------------------------------------------------------------------------------ | |
| always_see_output=0 | |
| no_args=0 | |
| if [ $# -eq 0 ] ; then | |
| no_args=1 | |
| fi | |
| if [ $# -eq 1 -a "$1" = "" ] ; then | |
| no_args=1 | |
| fi | |
| if [ $winelib -eq 1 ] ; then | |
| no_args=0 | |
| fi | |
| if [ $no_args -eq 1 ] ; then | |
| echo "Wine called with no arguments." | |
| echo "Invoking $WINEBIN/$WINE_BIN_NAME $@ ..." | |
| $XMESSAGE -buttons " Okay ":0," See the Wine Usage Statement ":1," Configure Wine ":2 \ | |
| -title "Welcome to Wine" \ | |
| " | |
| You have started Wine without specifying any arguments. | |
| Wine requires at least one argument - the name of the Windows | |
| application you would like to run. | |
| If you have launched this through the KDE menu system | |
| and your KDE installation is specially configured for Wine, | |
| then you can use the KDE file browser to select a Windows | |
| executable and then click on it to launch Wine with | |
| that application. | |
| You can similarly use the GNOME file manager to | |
| select a Windows executable and double click on it. | |
| If you would like to see the command line arguments | |
| for Wine, select the second option, below. | |
| " | |
| welcome_rc=$? | |
| if [ $welcome_rc -eq 0 ] ; then | |
| exit | |
| fi | |
| if [ $welcome_rc -eq 2 ] ; then | |
| launch_winesetup | |
| exit | |
| fi | |
| use_info_message=0 | |
| always_see_output=1 | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # No config file? Offer to help 'em out... | |
| #------------------------------------------------------------------------------ | |
| conf=0 | |
| while [ $conf -eq 0 ] ; do | |
| if [ -f ~/.winerc ] ; then | |
| conf=1 | |
| fi | |
| if [ -f ~/.wine/config ] ; then | |
| conf=2 | |
| fi | |
| if [ -f /etc/wine.conf ] ; then | |
| conf=3 | |
| fi | |
| if [ $conf -ne 0 ] ; then | |
| break; | |
| fi | |
| echo "No configuration file detected." | |
| $XMESSAGE -buttons " Cancel ":0," Proceed ":1," Configure Wine ":2 \ | |
| -title "Welcome to Wine" \ | |
| " | |
| You have started Wine, but we cannot find a Wine | |
| configuration file. | |
| This is normal if you have never run Wine before. | |
| If this is the case, select the 'Configure Wine' | |
| option, below, to create a configuration file. | |
| " | |
| init_rc=$? | |
| if [ $init_rc -eq 0 ] ; then | |
| exit | |
| fi | |
| if [ $init_rc -eq 1 ] ; then | |
| break | |
| fi | |
| if [ $init_rc -eq 2 ] ; then | |
| launch_winesetup | |
| fi | |
| # 127 == xmessage not available | |
| if [ $init_rc -eq 127 ] ; then | |
| exit | |
| fi | |
| done | |
| #------------------------------------------------------------------------------ | |
| # Optionally Warn the user we're going to be launching Wine... | |
| #------------------------------------------------------------------------------ | |
| if [ $use_info_message -ne 0 ] ; then | |
| echo "Invoking $WINEBIN/$WINE_BIN_NAME $@ ..." | |
| $XMESSAGE -timeout 30 -buttons " Dismiss ":0," Never display this message again ":3 \ | |
| -title "Wine Launch Window" \ | |
| "Invoking $WINEBIN/$WINE_BIN_NAME $@ ... | |
| This dialog box is a temporary status dialog to let you know | |
| that Wine is attempting to launch your application. | |
| Since Wine is still very much in a development stage, | |
| many applications will fail silently. | |
| This dialog box is your indication | |
| that we're *trying* to run your application. | |
| This dialog box will automatically disappear after 30 seconds, | |
| or after your application finishes. | |
| You can permanently disable this dialog by selecting | |
| the option below. | |
| " & | |
| info_message_pid=$! | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Here's a little function to clean up after that dialog... | |
| #------------------------------------------------------------------------------ | |
| clean_up_info_message () | |
| { | |
| if [ $use_info_message -ne 0 ] ; then | |
| #------------------------------------------------------------------------------ | |
| # Okay, make sure that the notice window is dead (and kill it if it ain't) | |
| #------------------------------------------------------------------------------ | |
| ps $info_message_pid >/dev/null 2>&1 | |
| if [ $? -ne 0 ] ; then | |
| wait $info_message_pid | |
| info_return=$? | |
| else | |
| info_return=0 | |
| kill $info_message_pid | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # If they didn't like the warning window, turn it off | |
| #------------------------------------------------------------------------------ | |
| if [ $info_return -eq 3 ] ; then | |
| $XMESSAGE -title "Wine Prelaunch Control" \ | |
| "Wine will now disable the prelaunch window you just saw. | |
| You will no longer be notified when Wine is attempting | |
| to start a Windows application. | |
| Please take note that you can reenable this window | |
| by removing the $info_flag file." -buttons " Okay ":0," Cancel ":1 | |
| if [ $? -eq 0 ] ; then | |
| touch $info_flag | |
| fi | |
| fi | |
| fi | |
| use_info_message=0 | |
| } | |
| #------------------------------------------------------------------------------ | |
| # Generate a temporary log file name | |
| #------------------------------------------------------------------------------ | |
| if [ -n "$TMP" ] ; then | |
| log_dir="$TMP" | |
| else | |
| log_dir="/tmp" | |
| fi | |
| use_log_name=0 | |
| log_name=`mktemp "$log_dir/wine.log.XXXXXX"` | |
| if [ $? -eq 0 ] ; then | |
| use_log_name=1 | |
| fi | |
| use_status_name=0 | |
| status_name=`mktemp "$log_dir/wine.status.XXXXXX"` | |
| if [ $? -eq 0 ] ; then | |
| use_status_name=1 | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Okay, really launch Wine... | |
| #------------------------------------------------------------------------------ | |
| if [ $use_log_name -ne 0 -a $use_status_name -ne 0 ] ; then | |
| ( $WINEBIN/$WINE_BIN_NAME "$@"; echo $? >$status_name ) 2>&1 | tee "$log_name" | |
| wine_return=`cat $status_name` | |
| else | |
| $WINEBIN/$WINE_BIN_NAME "$@" | |
| wine_return=$? | |
| fi | |
| if [ $use_status_name -ne 0 ] ; then | |
| rm -f $status_name | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Test the return code, and see if it fails | |
| #------------------------------------------------------------------------------ | |
| if [ $always_see_output -eq 0 -a $wine_return -eq 0 ] ; then | |
| echo "Wine exited with a successful status" | |
| if [ $use_log_name -ne 0 ] ; then | |
| rm -f "$log_name" | |
| fi | |
| else | |
| if [ $always_see_output -eq 0 ] ; then | |
| echo "Wine failed with return code $wine_return" | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Gracefully display a debug message if they like... | |
| #------------------------------------------------------------------------------ | |
| while [ $use_debug_message -gt 0 ] ; do | |
| #------------------------------------------------------------------------------ | |
| # Build up the menu of choices they can make... | |
| #------------------------------------------------------------------------------ | |
| BUTTONS=' Okay :0' | |
| if [ $use_log_name -ne 0 ] ; then | |
| BUTTONS="$BUTTONS"', View Log :1' | |
| fi | |
| BUTTONS="$BUTTONS"', Debug :2' | |
| BUTTONS="$BUTTONS"', Configure :4' | |
| BUTTONS="$BUTTONS"', Disable :3' | |
| #------------------------------------------------------------------------------ | |
| # Build an error message | |
| #------------------------------------------------------------------------------ | |
| MESSAGE=" | |
| Wine has exited with a failure status of $wine_return. | |
| Wine is still development software, so there can be many | |
| explanations for this problem. | |
| You can choose to run Wine again with a higher level | |
| of debug messages (the debug option, below). | |
| You can attempt to reconfigure Wine to make it work better. | |
| Note that one change you can make that will dramatically | |
| effect Wine's behaviour is to change whether or not | |
| Wine uses a true Windows partition, mounted under Linux, | |
| or whether it uses an empty Windows directory. | |
| The Wine Configuration program can assist you in making | |
| those changes (select Configure, below, for more). | |
| You can disable this message entirely by selecting the | |
| Disable option below." | |
| if [ $always_see_output -ne 0 -a $wine_return -eq 0 ] ; then | |
| MESSAGE=" | |
| Wine has exited with a failure status of $wine_return. | |
| You can disable this message entirely by selecting the | |
| Disable option below." | |
| fi | |
| if [ $use_log_name -ne 0 ] ; then | |
| MESSAGE="$MESSAGE | |
| Wine has captured a log of the Wine output in the file $log_name. | |
| You may view this file by selecting View Log, below." | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Display the message | |
| #------------------------------------------------------------------------------ | |
| $XMESSAGE -title "Wine Finished With Error" -buttons "$BUTTONS" "$MESSAGE" | |
| debug_return=$? | |
| #------------------------------------------------------------------------------ | |
| # Dismiss the other window... | |
| #------------------------------------------------------------------------------ | |
| clean_up_info_message | |
| #------------------------------------------------------------------------------ | |
| # Process a configure instruction | |
| #------------------------------------------------------------------------------ | |
| if [ $debug_return -eq 4 ] ; then | |
| launch_winesetup | |
| continue; | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # Process a view instruction | |
| #------------------------------------------------------------------------------ | |
| if [ $debug_return -eq 1 ] ; then | |
| $XMESSAGE -title "View Wine Log" -file "$log_name" -buttons " Okay ":0,"Delete $log_name":1 | |
| if [ $? -eq 1 ] ; then | |
| echo "Deleting $log_name" | |
| rm -f "$log_name" | |
| use_log_name=0 | |
| fi | |
| else | |
| use_debug_message=0 | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # If they didn't like the warning window, turn it off | |
| #------------------------------------------------------------------------------ | |
| if [ $debug_return -eq 3 ] ; then | |
| $XMESSAGE -title "Wine Debug Log Control" \ | |
| "Wine will now disable the Wine debug output control window you just saw. | |
| You will no longer be notified when Wine fails to start a | |
| Windows application. | |
| Please take note that you can reenable this window | |
| by removing the $debug_flag file." -buttons " Okay ":0," Cancel ":1 | |
| if [ $? -eq 0 ] ; then | |
| touch $debug_flag | |
| fi | |
| fi | |
| #------------------------------------------------------------------------------ | |
| # If they want to retry with debug, let 'em. | |
| #------------------------------------------------------------------------------ | |
| if [ $debug_return -eq 2 ] ; then | |
| echo "Rerunning WINEDEBUG=$debug_options $0 $@" | |
| WINEDEBUG=$debug_options exec $0 "$@" | |
| fi | |
| done | |
| fi | |
| clean_up_info_message | |
| # killed by signal? | |
| if [ $wine_return -ge 128 ]; then | |
| # try to kill myself with the same signal | |
| kill -$[wine_return - 128] $$ | |
| # if we get here the kill didn't work | |
| exit 1 | |
| fi |