Prevent memory leak and superfluous status notifications.
[wine] / programs / winelauncher.in
1 #!/bin/sh
2 #------------------------------------------------------------------------------
3 #   Winelauncher
4 #       This shell script attempts to intelligently manage the process
5 #   of launching a program with Wine.  It adds some level of
6 #   visual feedback to an end user.
7 #
8 #   Usage:
9 #       winelauncher [options]  "<windows program> [program arguments]"
10 #
11 #       This script is meant to be installed to /usr/bin/wine, and
12 #   to be used to invoke a Windows executable.
13 #       The options are passed through directly to Wine, and are
14 #   documented in the Wine man page.
15 #
16 #   Copyright (c) 2000 by Jeremy White for CodeWeavers
17 #
18 # This library is free software; you can redistribute it and/or
19 # modify it under the terms of the GNU Lesser General Public
20 # License as published by the Free Software Foundation; either
21 # version 2.1 of the License, or (at your option) any later version.
22 #
23 # This library is distributed in the hope that it will be useful,
24 # but WITHOUT ANY WARRANTY; without even the implied warranty of
25 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26 # Lesser General Public License for more details.
27 #
28 # You should have received a copy of the GNU Lesser General Public
29 # License along with this library; if not, write to the Free Software
30 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31 #------------------------------------------------------------------------------
32
33 #------------------------------------------------------------------------------
34 #  Primary configuration area - change this if you installed Wine to
35 #    a different location
36 #------------------------------------------------------------------------------
37 WINEBIN=@bindir@
38 WINELIB=@libdir@
39 WINESERVER=
40 WINEDLLPATH=@dlldir@
41
42 #------------------------------------------------------------------------------
43 #  Establish Color Scheme
44 #------------------------------------------------------------------------------
45 COLOR=' -xrm *.Command.background:darkgrey
46 -xrm *.Command.foreground:black
47 -xrm *.Text.background:black
48 -xrm *.Text.foreground:green
49 -xrm *.Form.background:grey
50 -xrm *.Form.foreground:green
51 -xrm *.foreground:green
52 -xrm *.background:black'
53
54
55 #------------------------------------------------------------------------------
56 #  Locate either xmessage or gmessage, if we can.
57 #------------------------------------------------------------------------------
58 type xmessage >/dev/null 2>/dev/null
59 if [ $? -ne 0 ] ; then
60     # xmessage not found; make sure the user notices this error
61     # (GUI users wouldn't even notice if we printed the text on console !)
62     MSGFILE=/tmp/WINE_CANNOT_FIND_XMESSAGE
63     cat > $MSGFILE << EOF
64 Warning:
65     The Wine launcher is unable to find the xmessage program,
66     which it needs to properly notify you of Wine execution status
67     or problems.
68
69     This launcher script relies heavily on finding this tool,
70     and without it, it will behave very poorly.
71
72     We strongly recommend that you use your distribution's
73     software methods to locate xmessage, or alternatively
74     use your favourite internet search engine to find out
75     how you are supposed to install xmessage on your system.
76 EOF
77
78     # try to display message file with tons of different X11 editors
79     # until we find one that's installed and working
80     for EDITPRG in nedit gedit kedit gvim xemacs; do
81       type $EDITPRG >/dev/null 2>/dev/null
82       if [ $? -eq 0 ] ; then
83         # execute editor and exit if successful
84         $EDITPRG $MSGFILE && exit
85       fi
86     done
87
88     # ok, we really give up now, this system is hosed ;-)
89     cat $MSGFILE
90 else
91     XMESSAGE="xmessage $COLOR"
92 fi
93
94 launch_winesetup()
95 {
96     which winesetup
97     if [ $? -eq 0 ] ; then
98         winesetup
99     else
100         if [ -x /opt/wine/bin/winesetup ] ; then
101             /opt/wine/bin/winesetup
102         else
103             $XMESSAGE -title "Error" \
104         "Error:  Unable to find winesetup in your PATH or in /opt/wine/bin:
105         I am not able to configure Wine.
106
107         If winesetup is being distributed in a separate package
108         that is not installed yet on your system, then please install this
109         package.
110         winesetup can also be downloaded from www.codeweavers.com.
111
112         If you choose to not use winesetup for configuration, then
113         you can find information on how to prepare a Wine config file manually
114         in the Wine README / README.gz file or in the Wine User Guide."
115         fi
116     fi
117 }
118
119 #------------------------------------------------------------------------------
120 #  We're going to do a lot of fancy footwork below.
121 #    Before we get started, it would be nice to know the argv0
122 #    of the actual script we're running (and lets remove at least
123 #    one level of symlinking).
124 #------------------------------------------------------------------------------
125 argv0_path=`which $0`
126 if [ -z $argv0_path ] ; then
127     argv0_path=$0
128 fi
129
130 real_name=`find $argv0_path -type l -printf "%l\n"`
131 if [ ! $real_name ]; then
132     real_name=$argv0_path
133 elif [ ! -x $real_name ]; then
134     real_name=`find $argv0_path -printf "%h\n"`/$real_name
135 fi
136
137 argv0_dir=`find $real_name -printf "%h\n"`
138
139 if [ -z $argv0_dir ] ; then
140     argv0_dir=.
141 fi
142
143 #------------------------------------------------------------------------------
144 #  Okay, now all that junk above was established at configure time.
145 #   However, if this is an RPM install, they may have chosen
146 #   to relocate this installation.  If so, that stuff above
147 #   is all broken and we should rejigger it.
148 #------------------------------------------------------------------------------
149 WINE_BIN_NAME=wine.bin
150 if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then
151     WINEBIN=`find $argv0_dir -maxdepth 1 -perm +0111 -type f -name "$WINE_BIN_NAME" -printf "%h\n" | head -n 1`
152 fi
153
154 if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then
155     WINEBIN=`find $argv0_dir/../ -maxdepth 1 -perm +0111 -type f -name "$WINE_BIN_NAME" -printf "%h\n" | head -n 1`
156 fi
157
158 if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then
159     WINE_BIN_NAME=wine
160     if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then
161         WINEBIN=`find $argv0_dir -maxdepth 1 -perm +0111 -type f -name "$WINE_BIN_NAME" -printf "%h\n" | head -n 1`
162     fi
163
164     if [ ! -x $WINEBIN/$WINE_BIN_NAME ] ; then
165         WINEBIN=`find $argv0_dir/../ -maxdepth 1 -perm +0111 -type f -name "$WINE_BIN_NAME" -printf "%h\n" | head -n 1`
166     fi
167 fi
168
169 if [ ! -r $WINELIB/libwine.so ] ; then
170     WINELIB=`find $argv0_dir -maxdepth 2 -name 'libwine.so' -printf "%h\n" | head -n 1`
171 fi
172
173 if [ ! -r $WINELIB/libwine.so ] ; then
174     WINELIB=`find $argv0_dir/../ -maxdepth 2 -name 'libwine.so' -printf "%h\n" | head -n 1`
175 fi
176
177 if [ -x $WINEBIN/wineserver ] ; then
178     WINESERVER=$WINEBIN/wineserver
179 fi
180
181 #------------------------------------------------------------------------------
182 #  Hey, if we built Wine from source, let's add a little extra fun to
183 #   mix it up a bit
184 #------------------------------------------------------------------------------
185 if [ -x $WINEBIN/server/wineserver ] ; then
186     WINESERVER=$WINEBIN/server/wineserver
187 fi
188
189 if [ -r $WINELIB/dlls/ntdll.dll.so ] ; then
190     WINEDLLPATH=$WINELIB/dlls
191 fi
192
193
194 #------------------------------------------------------------------------------
195 #  Okay, set the paths and move on.
196 #------------------------------------------------------------------------------
197 export LD_LIBRARY_PATH=$WINELIB:$LD_LIBRARY_PATH
198 export PATH=$WINEBIN:$PATH
199 export WINELOADER=$WINEBIN/$WINE_BIN_NAME
200 export WINEDLLPATH
201 export WINESERVER
202
203 info_flag=~/.wine/.no_prelaunch_window_flag
204 debug_flag=~/.wine/.no_debug_window_flag
205 debug_options="-debugmsg warn+all"
206
207 if [ -f $info_flag ] ; then
208     use_info_message=0
209 else
210     use_info_message=1
211 fi
212
213 if [ -f $debug_flag ] ; then
214     use_debug_message=0
215 else
216     use_debug_message=1
217 fi
218
219
220 #------------------------------------------------------------------------------
221 #  Handle winelib apps going through here
222 #------------------------------------------------------------------------------
223 winelib=0
224 if [ -f $argv0_path.so ] ; then
225     winelib=1
226     export WINEPRELOAD=$argv0_path.so
227 fi
228
229
230 #------------------------------------------------------------------------------
231 #  No arguments?  Help 'em out
232 #------------------------------------------------------------------------------
233 always_see_output=0
234 no_args=0
235 if [ $# -eq 0 ] ; then
236     no_args=1
237 fi
238
239 if [ $# -eq 1 -a "$1" = "" ] ; then
240     no_args=1
241 fi
242
243 if [ $winelib -eq 1 ] ; then
244     no_args=0
245 fi
246
247 if [ $no_args -eq 1 ] ; then
248     echo "Wine called with no arguments."
249     echo "Invoking $WINEBIN/$WINE_BIN_NAME $@ ..."
250     $XMESSAGE -buttons "    Okay    ":0," See the Wine Usage Statement ":1,"  Configure Wine  ":2 \
251         -title "Welcome to Wine" \
252         "
253
254         You have started Wine without specifying any arguments.
255
256         Wine requires at least one argument - the name of the Windows
257         application you would like to run.
258
259         If you have launched this through the KDE menu system
260         and your KDE installation is specially configured for Wine,
261         then you can use the KDE file browser to select a Windows
262         executable and then click on it to launch Wine with
263         that application.
264
265         You can similarly use the GNOME file manager to
266         select a Windows executable and double click on it.
267
268         If you would like to see the command line arguments
269         for Wine, select the second option, below.
270
271         "
272     welcome_rc=$?
273     if [ $welcome_rc -eq 0 ] ; then
274         exit
275     fi
276
277     if [ $welcome_rc -eq 2 ] ; then
278         launch_winesetup
279         exit
280     fi
281
282     use_info_message=0
283     always_see_output=1
284 fi
285
286 #------------------------------------------------------------------------------
287 #  No config file?  Offer to help 'em out...
288 #------------------------------------------------------------------------------
289 conf=0
290
291 while [ $conf -eq 0 ] ; do
292
293     if [ -f ~/.winerc ] ; then
294         conf=1
295     fi
296     if [ -f ~/.wine/config ] ; then
297         conf=2
298     fi
299     if [ -f /etc/wine.conf ] ; then
300         conf=3
301     fi
302
303     if [ $conf -ne 0 ] ; then
304         break;
305     fi
306
307     echo "No configuration file detected."
308     $XMESSAGE -buttons "    Cancel    ":0,"  Proceed   ":1,"  Configure Wine  ":2 \
309         -title "Welcome to Wine" \
310         "
311
312         You have started Wine, but we cannot find a Wine
313         configuration file.
314
315         This is normal if you have never run Wine before.
316         If this is the case, select the 'Configure Wine'
317         option, below, to create a configuration file.
318
319         "
320     init_rc=$?
321     if [ $init_rc -eq 0 ] ; then
322         exit
323     fi
324
325     if [ $init_rc -eq 1 ] ; then
326         break
327     fi
328
329     if [ $init_rc -eq 2 ] ; then
330         launch_winesetup
331     fi
332
333     # 127 == xmessage not available
334     if [ $init_rc -eq 127 ] ; then
335       exit
336     fi
337
338 done
339
340 #------------------------------------------------------------------------------
341 #  Optionally Warn the user we're going to be launching Wine...
342 #------------------------------------------------------------------------------
343 if [ $use_info_message -ne 0 ] ; then
344     echo "Invoking $WINEBIN/$WINE_BIN_NAME $@ ..."
345     $XMESSAGE -timeout 30 -buttons "    Dismiss    ":0," Never display this message again ":3 \
346         -title "Wine Launch Window" \
347         "Invoking $WINEBIN/$WINE_BIN_NAME $@ ...
348
349         This dialog box is a temporary status dialog to let you know
350         that Wine is attempting to launch your application.
351
352         Since Wine is still very much in a development stage,
353         many applications will fail silently.
354         This dialog box is your indication
355         that we're *trying* to run your application.
356
357         This dialog box will automatically disappear after 30 seconds,
358         or after your application finishes.
359
360         You can permanently disable this dialog by selecting
361         the option below.
362         " &
363     info_message_pid=$!
364 fi
365
366 #------------------------------------------------------------------------------
367 #  Here's a little function to clean up after that dialog...
368 #------------------------------------------------------------------------------
369 clean_up_info_message ()
370 {
371     if [ $use_info_message -ne 0 ] ; then
372
373         #------------------------------------------------------------------------------
374         #  Okay, make sure that the notice window is dead (and kill it if it ain't)
375         #------------------------------------------------------------------------------
376         ps $info_message_pid >/dev/null 2>&1
377         if [ $? -ne 0 ] ; then
378             wait $info_message_pid
379             info_return=$?
380         else
381             info_return=0
382             kill $info_message_pid
383         fi
384
385         #------------------------------------------------------------------------------
386         #  If they didn't like the warning window, turn it off
387         #------------------------------------------------------------------------------
388         if [ $info_return -eq 3 ] ; then
389             $XMESSAGE -title "Wine Prelaunch Control" \
390             "Wine will now disable the prelaunch window you just saw.
391             You will no longer be notified when Wine is attempting
392             to start a Windows application.
393
394             Please take note that you can reenable this window
395             by removing the $info_flag file." -buttons "  Okay  ":0," Cancel ":1
396             if [ $? -eq 0 ] ; then
397                 touch $info_flag
398             fi
399         fi
400     fi
401
402     use_info_message=0
403 }
404 #------------------------------------------------------------------------------
405 #  Generate a temporary log file name
406 #------------------------------------------------------------------------------
407 if [ -n "$TMP" ] ; then
408   log_dir="$TMP"
409 else
410   log_dir="/tmp"
411 fi
412 use_log_name=0
413 log_name=`mktemp "$log_dir/wine.log.XXXXXX"`
414 if [ $? -eq 0 ] ; then
415     use_log_name=1
416 fi
417 use_status_name=0
418 status_name=`mktemp "$log_dir/wine.status.XXXXXX"`
419 if [ $? -eq 0 ] ; then
420     use_status_name=1
421 fi
422
423 #------------------------------------------------------------------------------
424 #  Okay, really launch Wine...
425 #------------------------------------------------------------------------------
426 if [ $use_log_name -ne 0 -a $use_status_name -ne 0 ] ; then
427     ( $WINEBIN/$WINE_BIN_NAME "$@"; echo $? >$status_name ) 2>&1 | tee "$log_name"
428     wine_return=`cat $status_name`
429 else
430     $WINEBIN/$WINE_BIN_NAME "$@"
431     wine_return=$?
432 fi
433 if [ $use_status_name -ne 0 ] ; then
434     rm -f $status_name
435 fi
436
437 #------------------------------------------------------------------------------
438 #  Test the return code, and see if it fails
439 #------------------------------------------------------------------------------
440 if [ $always_see_output -eq 0 -a $wine_return -eq 0 ] ; then
441     echo "Wine exited with a successful status"
442     if [ $use_log_name -ne 0 ] ; then
443         rm -f "$log_name"
444     fi
445 else
446     if [ $always_see_output -eq 0 ] ; then
447         echo "Wine failed with return code $wine_return"
448     fi
449
450     #------------------------------------------------------------------------------
451     #  Gracefully display a debug message if they like...
452     #------------------------------------------------------------------------------
453     while [ $use_debug_message -gt 0 ] ; do
454
455         #------------------------------------------------------------------------------
456         #  Build up the menu of choices they can make...
457         #------------------------------------------------------------------------------
458         BUTTONS='    Okay    :0'
459         if [ $use_log_name -ne 0 ] ; then
460             BUTTONS="$BUTTONS"', View Log :1'
461         fi
462
463         BUTTONS="$BUTTONS"',  Debug  :2'
464         BUTTONS="$BUTTONS"',  Configure :4'
465         BUTTONS="$BUTTONS"',  Disable :3'
466
467         #------------------------------------------------------------------------------
468         #  Build an error message
469         #------------------------------------------------------------------------------
470         MESSAGE="
471 Wine has exited with a failure status of $wine_return.
472
473 Wine is still development software, so there can be many
474 explanations for this problem.
475
476 You can choose to run Wine again with a higher level
477 of debug messages (the debug option, below).
478
479 You can attempt to reconfigure Wine to make it work better.
480 Note that one change you can make that will dramatically
481 effect Wine's behaviour is to change whether or not
482 Wine uses a true Windows partition, mounted under Linux,
483 or whether it uses an empty Windows directory.
484 The Wine Configuration program can assist you in making
485 those changes (select Configure, below, for more).
486
487 You can disable this message entirely by selecting the
488 Disable option below."
489
490         if [ $always_see_output -ne 0 -a $wine_return -eq 0 ] ; then
491             MESSAGE="
492 Wine has exited with a failure status of $wine_return.
493
494 You can disable this message entirely by selecting the
495 Disable option below."
496
497         fi
498
499         if [ $use_log_name -ne 0 ] ; then
500             MESSAGE="$MESSAGE
501
502 Wine has captured a log of the Wine output in the file $log_name.
503 You may view this file by selecting View Log, below."
504         fi
505
506         #------------------------------------------------------------------------------
507         #  Display the message
508         #------------------------------------------------------------------------------
509         $XMESSAGE -title "Wine Finished With Error" -buttons "$BUTTONS" "$MESSAGE"
510         debug_return=$?
511
512         #------------------------------------------------------------------------------
513         #  Dismiss the other window...
514         #------------------------------------------------------------------------------
515         clean_up_info_message
516
517         #------------------------------------------------------------------------------
518         #  Process a configure instruction
519         #------------------------------------------------------------------------------
520         if [ $debug_return -eq 4 ] ; then
521             launch_winesetup
522             continue;
523         fi
524
525         #------------------------------------------------------------------------------
526         #  Process a view instruction
527         #------------------------------------------------------------------------------
528         if [ $debug_return -eq 1 ] ; then
529             $XMESSAGE -title "View Wine Log" -file "$log_name" -buttons "  Okay  ":0,"Delete $log_name":1
530             if [ $? -eq 1 ] ; then
531                 echo "Deleting $log_name"
532                 rm -f "$log_name"
533                 use_log_name=0
534             fi
535         else
536             use_debug_message=0
537         fi
538
539         #------------------------------------------------------------------------------
540         #  If they didn't like the warning window, turn it off
541         #------------------------------------------------------------------------------
542         if [ $debug_return -eq 3 ] ; then
543             $XMESSAGE -title "Wine Debug Log Control" \
544             "Wine will now disable the Wine debug output control window you just saw.
545             You will no longer be notified when Wine fails to start a
546             Windows application.
547
548             Please take note that you can reenable this window
549             by removing the $debug_flag file." -buttons "  Okay  ":0," Cancel ":1
550
551             if [ $? -eq 0 ] ; then
552                 touch $debug_flag
553             fi
554
555         fi
556
557         #------------------------------------------------------------------------------
558         #  If they want to retry with debug, let 'em.
559         #------------------------------------------------------------------------------
560         if [ $debug_return -eq 2 ] ; then
561             echo "Rerunning $0 $debug_options $@"
562             exec $0 $debug_options "$@"
563         fi
564     done
565 fi
566
567
568 clean_up_info_message
569
570 # killed by signal?
571 if [ $wine_return -ge 128 ]; then
572         # try to kill myself with the same signal
573         kill -$[wine_return - 128] $$
574         # if we get here the kill didn't work
575         exit 1
576 fi