Fix memory leak in error path.
[wine] / tools / bug_report.pl
1 #!/usr/bin/perl -w
2 ##Wine Quick Debug Report Maker Thingy (WQDRMK)
3 ## Copyright (c) 1998-1999 Adam Sacarny jazz@cscweb.net ICQ: 19617831
4 ##Do not say this is yours without my express permisson, or I will
5 ##hunt you down and kill you like the savage animal I am.
6 ##
7 ## Improvements by Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
8 ## (c) 2000
9 ##
10 ## A few improovements and updates here and there
11 ## Copyright 2003-2004 Ivan Leo Puoti
12 ##
13 ## This library is free software; you can redistribute it and/or
14 ## modify it under the terms of the GNU Lesser General Public
15 ## License as published by the Free Software Foundation; either
16 ## version 2.1 of the License, or (at your option) any later version.
17 ##
18 ## This library is distributed in the hope that it will be useful,
19 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 ## Lesser General Public License for more details.
22 ##
23 ## You should have received a copy of the GNU Lesser General Public
24 ## License along with this library; if not, write to the Free Software
25 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ##
27 ##Changelog:
28 ##August 29, 1999 - Work around for debugger exit (or lack thereof)
29 ##                - Should now put debugging output in correct place
30 ##April 19, 1999 - Much nicer way to select Wine's location
31 ##               - Option to disable creation of a debugging output
32 ##               - Now places debugging output where it was started
33 ##April 4, 1999 - Sanity check for file locations/wine strippedness
34 ##              - Various code cleanups/fixes
35 ##March 21, 1999 - Bash 2.0 STDERR workaround (Thanks Ryan Cumming!)
36 ##March 1, 1999 - Check for stripped build
37 ##February 3, 1999 - Fix to chdir to the program's directory
38 ##February 1, 1999 - Cleaned up code
39 ##January 26, 1999 - Fixed various bugs...
40 ##                 - Made newbie mode easier
41 ##January 25, 1999 - Initial Release
42 use strict;
43 sub do_var($) {
44         my $var=$_[0];
45         $var =~ s/\t//g;
46         return $var;
47 }
48 open STDERR, ">&SAVEERR"; open STDERR, ">&STDOUT";
49 $ENV{'SHELL'}="/bin/bash";
50 my $var0 = qq{
51         What is your level of Wine expertise? 1-newbie 2-intermediate 3-advanced
52
53         1 - Makes a debug report as defined in the Wine documentation. Best
54             for new Wine users. If you're not sure what WINEDEBUG is, then
55             use this mode.
56         2 - Makes a debug report that is more customizable (Example: you can
57             choose what WINEDEBUG to use). You are asked more questions in
58             this mode. May intimidate newbies.
59         3 - Just like 2, but not corner cutting. Assumes you know what you're
60             doing so it leaves out the long descriptions.
61 };
62 print do_var($var0)."\n";
63 my $debuglevel=0;
64 until ($debuglevel >= 1 and $debuglevel <= 3) {
65         print "Enter your level of Wine expertise (1-3): ";
66         $debuglevel=<STDIN>;
67         chomp $debuglevel;
68 }
69
70 if ($debuglevel < 3) {
71         my $var1 = qq{
72         This program will make a debug report for Wine developers. It generates
73         two files. The first one has everything asked for by the bugreports guide;
74         the second has *all* of the debug output, which can go to thousands of
75         lines.
76         To (hopefully) get the bug fixed, report it to the project
77         bug tracking system at http://bugs.winehq.org.
78         Attach the first file to the bug description.
79         Also include detailed description of the problem. The developers
80         might ask you for "the last X lines from the report". If so, just
81         provide the output of the following command:
82             gzip -d (output file) | tail -n (X) > outfile
83         If you do not want to create one of the files, just specify "no file".
84         };
85         print do_var($var1);
86 } elsif ($debuglevel =~ 3) {
87         my $var2 = qq{
88         This program will output to two files:
89         1. Formatted debug report you might want to post to the newsgroup
90         2. File with ALL the debug output (It will later be compressed with
91         gzip, so leave off the trailing .gz)
92         If you do not want to create one of the files, just type in "no file"
93         and I'll skip it.
94         };
95         print do_var($var2);
96 }
97
98 print "\nFilename for the formatted debug report: ";
99 my $outfile=<STDIN>;
100 chomp $outfile;
101 my $var23 = qq{
102 I don't think you typed in the right filename. Let's try again.
103 };
104 while ($outfile =~ /^(\s)*$/) {
105         print do_var($var23);
106         $outfile=<STDIN>;
107         chomp $outfile;
108 }
109
110 print "Filename for full debug output: ";
111 my $dbgoutfile=<STDIN>;
112 chomp $dbgoutfile;
113 while ($dbgoutfile =~ /^(\s)*$/) {
114         print do_var($var23);
115         $dbgoutfile=<STDIN>;
116         chomp $dbgoutfile;
117 }
118
119 my $var31 = qq{
120 Since you will only be creating the formatted report, I will need a
121 temporary place to put the full output.
122 You may not enter "no file" for this.
123 Enter the filename for the temporary file:
124 };
125 my $tmpoutfile;
126 if ($outfile ne "no file" and $dbgoutfile eq "no file") {
127         print do_var($var31);
128         $tmpoutfile=<STDIN>;
129         chomp $tmpoutfile;
130         while (($tmpoutfile =~ /^(\s)*$/) or ($tmpoutfile eq "no file")) {
131                 print do_var($var23);
132                 $tmpoutfile=<STDIN>;
133                 chomp $tmpoutfile;
134         }
135 }
136
137 my $whereis=`whereis wine`;
138 chomp $whereis;
139 print "\nWhere is your copy of Wine located?\n\n";
140 $whereis =~ s/^wine\: //;
141 my @locations = split(/\s/,$whereis);
142 print "1 - Unlisted (I'll prompt you for a new location\n";
143 print "2 - Unsure (I'll use #3, that's probably it)\n";
144 my $i=2;
145 foreach my $location (@locations) {
146         $i++;
147         print "$i - $location\n";
148 }
149 print "\n";
150 sub select_wineloc() {
151         my $wineloc;
152         do
153                 {
154                 print "Enter the number that corresponds to Wine's location: ";
155                 $wineloc=<STDIN>;
156                 chomp $wineloc;
157                 }
158         while ( ! ( $wineloc >=1 and $wineloc <= 2+@locations ) );
159         if ($wineloc == 1) {
160                 my $var25 = qq{
161                 Enter the full path to wine (Example: /usr/bin/wine):
162                 };
163                 my $var26 = qq{
164                 Please enter the full path to wine. A full path is the
165                 directories leading up to a program's location, and then the
166                 program. For example, if you had the program "wine" in the
167                 directory "/usr/bin", you would type in "/usr/bin/wine". Now
168                 try:
169                 };
170                 print do_var($var25) if $debuglevel == 3;
171                 print do_var($var26) if $debuglevel < 3;
172                 $wineloc=<STDIN>;
173                 chomp $wineloc;
174                 while ($wineloc =~ /^(\s)*$/) {
175                         print do_var($var23);
176                         $wineloc=<STDIN>;
177                         chomp $wineloc;
178                 }
179         }
180         elsif ($wineloc == 2) {
181                 $wineloc=$locations[0];
182         }
183         else {
184                 $wineloc=$locations[$wineloc-3];
185         }
186         return $wineloc;
187 }
188 my $wineloc=select_wineloc();
189 print "Checking if $wineloc is stripped...\n";
190 my $ifstrip = `nm $wineloc 2>&1`;
191 while ($ifstrip =~ /no symbols/) {
192         my $var24 = qq{
193         Your wine is stripped! Stripped versions make useless debug reports
194         If you have another location of wine that may be used, enter it now.
195         Otherwise, hit control-c and download an unstripped (Debug) version, then re-run
196         this script.
197         };
198         print do_var($var24);
199         $wineloc=select_wineloc();
200         $ifstrip = `nm $wineloc 2>&1`;
201 }
202 while ($ifstrip =~ /not recognized/) {
203         my $var26 = qq{
204         Looks like you gave me something that isn't a Wine binary (It could be a
205         text file). Try again.
206         };
207         print do_var($var26);
208         $wineloc=select_wineloc();
209         print "Checking if $wineloc is stripped...\n";
210         $ifstrip = `nm $wineloc 2>&1`;
211 }
212
213 print "\nWhat version of Windows are you using with Wine?\n\n".
214       "0 - None\n".
215       "1 - Windows 3.x\n".
216       "2 - Windows 95\n".
217       "3 - Windows 98\n".
218       "4 - Windows ME\n".
219       "5 - Windows NT 3.5x\n".
220       "6 - Windows NT4.x\n".
221       "7 - Windows 2000\n".
222       "8 - Windows XP\n".
223       "9 - Windows Server 2003\n".
224       "10 - Other\n\n";
225 my $winver;
226 do
227         {
228         print "Enter the number that corresponds to your Windows version: ";
229         $winver=<STDIN>;
230         chomp $winver;
231         }
232 until ($winver >= 0 and $winver <= 10);
233 if ($winver =~ 0) {
234         $winver="None Installed";
235 } elsif ($winver =~ 1) {
236         $winver="Windows 3.x";
237 } elsif ($winver =~ 2) {
238         $winver="Windows 95";
239 } elsif ($winver =~ 3) {
240         $winver="Windows 98";
241 } elsif ($winver =~ 4) {
242         $winver="Windows ME";
243 } elsif ($winver =~ 5) {
244         $winver="Windows NT 3.5x";
245 } elsif ($winver =~ 6) {
246         $winver="Windows NT 4.x";
247 } elsif ($winver =~ 7) {
248         $winver="Windows 2000";
249 } elsif ($winver =~ 8) {
250         $winver="Windows XP";
251 } elsif ($winver =~ 9) {
252         $winver="Windows Server 2003";
253 } elsif ($winver =~ 10) {
254         print "What version of Windows are you using? ";
255         $winver=<STDIN>;
256         chomp $winver;
257 }
258 if ($debuglevel < 3) {
259         my $var7 = qq{
260         Enter the full path to the program you want to run. Remember what you
261         were told before - a full path is the directories leading up to the
262         program and then the program's name, like /dos/windows/sol.exe, not
263         sol.exe:
264         };
265         print do_var($var7);
266 }
267 if ($debuglevel =~ 3) {
268         my $var8 = qq{
269         Enter the full path to the program you want to run (Example:
270         /dos/windows/sol.exe, NOT sol.exe):
271         };
272         print do_var($var8);
273 }
274 my $program=<STDIN>;
275 chomp $program;
276 while ($program =~ /^(\s)*$/) {
277         print do_var($var23);
278         $program=<STDIN>;
279         chomp $program;
280 }
281 $program =~ s/\"//g;
282 my $var9 = qq{
283 Enter the name, version, and manufacturer of the program (Example:
284 Netscape Navigator 4.5):
285 };
286 print do_var($var9);
287 my $progname=<STDIN>;
288 chomp $progname;
289 my $var10 = qq{
290 Enter 1 if your program is 16 bit (Windows 3.x), 2 if your program is 32
291 bit (Windows 95, NT3.x and up), or 3 if you are unsure:
292 };
293 print do_var($var10);
294 my $progbits=<STDIN>;
295 chomp $progbits;
296 until ($progbits == 1 or $progbits == 2 or $progbits == 3) {
297         print "You must enter 1, 2 or 3!\n";
298         $progbits=<STDIN>;
299         chomp $progbits
300 }
301 if ($progbits =~ 1) {
302         $progbits = "Win16";
303 } elsif ($progbits =~ 2) {
304         $progbits = "Win32";
305 } else {
306         $progbits = "Unsure";
307 }
308 my $debugopts;
309 if ($debuglevel > 1) {
310         if ($debuglevel =~ 2) {
311                 my $var11 = qq{
312                 Enter any extra debug options. Default is +relay - If you don't
313                 know what options to use, just hit enter, and I'll use those (Example, the
314                 developer tells you to re-run with WINEDEBUG=+dosfs,+module you would type
315                 in +dosfs,+module). Hit enter if you're not sure what to do:
316                 };
317                 print do_var($var11);
318         } elsif ($debuglevel =~ 3) {
319                 my $var12 = qq{
320                 Enter any debug options you would like to use. Just enter parts after
321                 WINEDEBUG. Default is +relay:
322                 };
323                 print do_var($var12);
324         }
325         $debugopts=<STDIN>;
326         chomp $debugopts;
327         if ($debugopts =~ /--debugmsg /) {
328                 $debugopts = (split / /,$debugopts)[1];
329         }
330         if ($debugopts =~ /WINEDEBUG= /) {
331                 $debugopts = (split / /,$debugopts)[1];
332         }
333         if ($debugopts =~ /^\s*$/) {
334                 $debugopts="+relay";
335         }
336 } elsif ($debuglevel =~ 1) {
337         $debugopts = "+relay";
338 }
339 my $lastnlines;
340 if ($debuglevel > 1) {
341         if ($debuglevel =~ 2) {
342                 my $var13 = qq{
343                 How many trailing lines of debugging info do you want to include in the report
344                 you're going to submit (First file)? If a developer asks you to include
345                 the last 15000 lines, enter 15000 here. Default is 3000, which is reached by
346                 pressing enter. (If you're not sure, just hit enter):
347                 };
348                 print do_var($var13);
349         } elsif ($debuglevel =~ 3) {
350                 my $var14 = qq{
351                 Enter how many lines of trailing debugging output you want in your nice
352                 formatted report. Default is 3000:
353                 };
354                 print do_var($var14);
355         }
356         $lastnlines=<STDIN>;
357         chomp $lastnlines;
358         if ($lastnlines =~ /^\s*$/) {
359         $lastnlines=3000;
360         }
361 } elsif ($debuglevel =~ 1) {
362         $lastnlines=3000;
363 }
364 my $extraops;
365 if ($debuglevel > 1) {
366         my $var15 = qq{
367         Enter any extra options you want to pass to Wine.
368         };
369         print do_var($var15);
370         $extraops=<STDIN>;
371         chomp $extraops;
372 } elsif ($debuglevel =~ 1) {
373         $extraops=" ";
374 }
375
376 print "\nEnter the name of your distribution (Example: RedHat 9.0): ";
377 my $dist=<STDIN>;
378 chomp $dist;
379
380 my $configopts;
381 if ($debuglevel > 1) {
382         if ($debuglevel =~ 2) {
383                 my $var16 = qq{
384                 When you ran ./configure to build wine, were there any special options
385                 you used to do so (Example: --enable-dll)? If you didn't use any special
386                 options or didn't compile Wine yourself, just hit enter:
387                 };
388                 print do_var($var16);
389         } elsif ($debuglevel =~ 3) {
390                 my $var17 = qq{
391                 Enter any special options you used when running ./configure for Wine
392                 (Default is none, use if you didn't compile Wine yourself):
393                 };
394                 print do_var($var17);
395         }
396         $configopts=<STDIN>;
397         chomp $configopts;
398         if ($configopts =~ /^\s*$/) {
399         $configopts="None";
400         }
401 } elsif ($debuglevel =~ 1) {
402         $configopts="None";
403 }
404 my $winever;
405 if ($debuglevel > 1) {
406         if ($debuglevel =~ 2) {
407                 my $var18 = qq{
408                 Is your Wine version CVS or from a .tar.gz or RPM file? As in... did you download it
409                 off a website/ftpsite or did you/have you run cvs on it to update it?
410                 For CVS: YYYYMMDD, where YYYY is the year (2004), MM is the month (03), and DD
411                 is the day (09), that you last updated it (Example: 20040309).
412                 For tar.gz and RPM: Just hit enter and I'll figure out the version for you:
413                 };
414                 print do_var($var18);
415         } elsif ($debuglevel =~ 3) {
416                 my $var19 = qq{
417                 Is your Wine from CVS? Enter the last CVS update date for it here, in
418                 YYYYMMDD form (If it's from a tarball or RPM, just hit enter):
419                 };
420                 print do_var($var19);
421         }
422         $winever=<STDIN>;
423         chomp $winever;
424         if ($winever =~ /[0-9]+/) {
425                 $winever .= " CVS";
426         }
427         else {
428                 $winever = `$wineloc -v 2>&1`;
429                 chomp $winever;
430         }
431 } elsif ($debuglevel =~ 1) {
432         $winever=`$wineloc -v 2>&1`;
433         chomp $winever;
434 }
435 my $gccver=`gcc -v 2>&1`;
436 $gccver = (split /\n/,$gccver)[1];
437 chomp $gccver;
438 my $cpu=`uname -m`;
439 chomp $cpu;
440 my $kernelver=`uname -r`;
441 chomp $kernelver;
442 my $ostype=`uname -s`;
443 chomp $ostype;
444 my $wineneeds=`ldd $wineloc`;
445 if ($debuglevel < 3) {
446         my $var20 = qq{
447         OK, now I'm going to run Wine. I will close it for you once the Wine
448         debugger comes up. NOTE: You won't see ANY debug messages. Don't
449         worry, they are being output to a file. Since there are so many, it's
450         not a good idea to have them all output to a terminal (Speed slowdown
451         mainly).
452         Wine will still run much slower than normal, because there will be so
453         many debug messages being output to file.
454         };
455         print do_var($var20);
456 } elsif ($debuglevel =~ 3) {
457         my $var21 = qq{
458         OK, now it's time to run Wine. I will close down Wine for you after
459         the debugger is finished doing its thing.
460         };
461         print do_var($var21);
462 }
463 print "Hit enter to start Wine!\n";
464 <STDIN>;
465 my $dir=$program;
466 $dir=~m#(.*)/#;
467 $dir=$1;
468 use Cwd;
469 my $nowdir=getcwd;
470 chdir($dir);
471 if (!($outfile =~ /\//) and $outfile ne "no file") {
472         $outfile = "$nowdir/$outfile";
473 }
474 if (!($dbgoutfile =~ /\//) and $dbgoutfile ne "no file") {
475         $dbgoutfile = "$nowdir/$dbgoutfile";
476 }
477 if (!($tmpoutfile =~ /\//)) {
478         $tmpoutfile = "$nowdir/$tmpoutfile";
479 }
480 $SIG{CHLD}=$SIG{CLD}=sub { wait };
481 my $lastlines;
482 sub generate_outfile();
483 if ($dbgoutfile ne "no file") {
484         unlink("$dbgoutfile");
485         my $pid=fork();
486         if ($pid) {
487         }
488         elsif (defined $pid) {
489                 close(0);close(1);close(2);
490                 exec "echo quit | WINEDEBUG=$debugopts $wineloc $extraops \"$program\" > $dbgoutfile 2>&1";
491         }
492         else {
493                 die "couldn't fork";
494         }
495         while (kill(0, $pid)) {
496                 sleep(5);
497                 my $last = `tail -n 5 $dbgoutfile | grep Wine-dbg`;
498                 if ($last =~ /Wine-dbg/) {
499                         kill "TERM", $pid;
500                         last;
501                 }
502         }
503         if ($outfile ne "no file") {
504                 $lastlines=`tail -n $lastnlines $dbgoutfile`;
505                 system("gzip $dbgoutfile");
506                 generate_outfile();
507         }
508         else {
509                 system("gzip $dbgoutfile");
510         }
511 }
512 elsif ($outfile ne "no file" and $dbgoutfile eq "no file") {
513         my $pid=fork();
514         if ($pid) {
515         }
516         elsif (defined $pid) {
517                 close(0);close(1);close(2);
518                 exec "echo quit | WINEDEBUG=$debugopts $wineloc $extraops \"$program\" 2>&1| tee $tmpoutfile | tail -n $lastnlines > $outfile";
519         }
520         else {
521                 die "couldn't fork";
522         }
523         print "$outfile $tmpoutfile";
524         while (kill(0, $pid)) {
525                 sleep(5);
526                 my $last = `tail -n 5 $tmpoutfile | grep Wine-dbg`;
527                 if ($last =~ /Wine-dbg/) {
528                         kill "TERM", $pid;
529                         last;
530                 }
531         }
532         unlink($tmpoutfile);
533         open(OUTFILE, "$outfile");
534         while (<OUTFILE>) {
535                 $lastlines .= $_;
536         }
537         close(OUTFILE);
538         unlink($outfile);
539         generate_outfile();
540 }
541 else {
542         my $var27 = qq{
543         I guess you don't want me to make any debugging output. I'll send
544         it to your terminal. This will be a *lot* of output -- hit enter to
545         continue, control-c to quit.
546         Repeat: this will be a lot of output!
547         };
548         print do_var($var27);
549         <STDIN>;
550         system("$wineloc WINEDEBUG=$debugopts $extraops \"$program\"");
551 }
552 sub generate_outfile() {
553 open(OUTFILE,">$outfile");
554 print OUTFILE <<EOM;
555 Auto-generated debug report by Wine Quick Debug Report Maker Tool:
556 WINE Version:                $winever
557 Windows Version:             $winver
558 Distribution:                $dist
559 Kernel Version:              $kernelver
560 OS Type:                     $ostype
561 CPU:                         $cpu
562 GCC Version:                 $gccver
563 Program:                     $progname
564 Program Type:                $progbits
565 Debug Options:               WINEDEBUG=$debugopts
566 Other Extra Commands Passed: $extraops
567 Extra ./configure Commands:  $configopts
568 Wine Dependencies:
569 $wineneeds
570 Last $lastnlines lines of debug output follows:
571 $lastlines
572 I have a copy of the full debug report, if it is needed.
573 Thank you!
574 EOM
575 }
576 my $var22 = qq{
577 Great! We're finished making the debug report. Please go to http://bugs.winehq.org
578 and enter it as a new bug. Check that nobody has already reported the same bug!
579 };
580 my $var28 = qq{
581 The filename for the formatted report is:
582 $outfile
583 };
584 my $var29 = qq{
585 The filename for the compressed full debug is:
586 $dbgoutfile.gz
587 Note that it is $dbgoutfile.gz, since I compressed it with gzip for you.
588 };
589 my $var30 = qq{
590 If you have any problems with this bug reporting tool,
591 please submit a bug report to Wine bugtracking system at http://bugs.winehq.org
592 or tell the Wine newsgroup (comp.emulators.ms-windows.wine).
593 };
594 print do_var($var22);
595 print do_var($var28) if $outfile ne "no file";
596 print do_var($var29) if $dbgoutfile ne "no file";
597 print do_var($var30);