xref: /openbsd-src/gnu/usr.bin/perl/utils/perlbug.PL (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1#!/usr/local/bin/perl
2
3use Config;
4use File::Basename qw(&basename &dirname);
5use Cwd;
6use File::Spec::Functions;
7
8# List explicitly here the variables you want Configure to
9# generate.  Metaconfig only looks for shell variables, so you
10# have to mention them as if they were shell variables, not
11# %Config entries.  Thus you write
12#  $startperl
13# to ensure Configure will look for $Config{startperl}.
14#  $perlpath
15
16# This forces PL files to create target in same directory as PL file.
17# This is so that make depend always knows where to find PL derivatives.
18$origdir = cwd;
19chdir dirname($0);
20$file = basename($0, '.PL');
21$file .= '.com' if $^O eq 'VMS';
22
23open OUT, ">$file" or die "Can't create $file: $!";
24
25# extract patchlevel.h information
26
27open PATCH_LEVEL, "<" . catfile(updir, "patchlevel.h")
28    or die "Can't open patchlevel.h: $!";
29
30my $patchlevel_date = (stat PATCH_LEVEL)[9];
31
32while (<PATCH_LEVEL>) {
33    last if $_ =~ /^\s*static\s+(?:const\s+)?char.*?local_patches\[\]\s*=\s*{\s*$/;
34}
35
36if (! defined($_)) {
37    warn "Warning: local_patches section not found in patchlevel.h\n";
38}
39
40my @patches;
41while (<PATCH_LEVEL>) {
42    last if /^\s*}/;
43    next if /^\s*#/;  # preprocessor stuff
44    next if /PERL_GIT_UNPUSHED_COMMITS/;    # XXX expand instead
45    next if /"uncommitted-changes"/;        # XXX determine if active instead
46    chomp;
47    s/^\s+,?\s*"?//;
48    s/"?\s*,?$//;
49    s/(['\\])/\\$1/g;
50    push @patches, $_ unless $_ eq 'NULL';
51}
52my $patch_desc = "'" . join("',\n    '", @patches) . "'";
53my $patch_tags = join "", map /(\S+)/ ? "+$1 " : (), @patches;
54
55close(PATCH_LEVEL) or die "Error closing patchlevel.h: $!";
56
57# TO DO (prehaps): store/embed $Config::config_sh into perlbug. When perlbug is
58# used, compare $Config::config_sh with the stored version. If they differ then
59# append a list of individual differences to the bug report.
60
61
62print "Extracting $file (with variable substitutions)\n";
63
64# In this section, perl variables will be expanded during extraction.
65# You can use $Config{...} to use Configure variables.
66
67my $extract_version = sprintf("%vd", $^V);
68
69print OUT <<"!GROK!THIS!";
70$Config{startperl}
71    eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
72	if \$running_under_some_shell;
73
74my \$config_tag1 = '$extract_version - $Config{cf_time}';
75
76my \$patchlevel_date = $patchlevel_date;
77my \$patch_tags = '$patch_tags';
78my \@patches = (
79    $patch_desc
80);
81!GROK!THIS!
82
83# In the following, perl variables are not expanded during extraction.
84
85print OUT <<'!NO!SUBS!';
86
87use warnings;
88use strict;
89use Config;
90use File::Spec;		# keep perlbug Perl 5.005 compatible
91use Getopt::Std;
92use File::Basename 'basename';
93
94sub paraprint;
95
96BEGIN {
97    eval { require Mail::Send;};
98    $::HaveSend = ($@ eq "");
99    eval { require Mail::Util; } ;
100    $::HaveUtil = ($@ eq "");
101    # use secure tempfiles wherever possible
102    eval { require File::Temp; };
103    $::HaveTemp = ($@ eq "");
104    eval { require Module::CoreList; };
105    $::HaveCoreList = ($@ eq "");
106};
107
108my $Version = "1.39";
109
110#TODO:
111#       make sure failure (transmission-wise) of Mail::Send is accounted for.
112#       (This may work now. Unsure of the original author's issue -JESSE 2008-06-08)
113#       - Test -b option
114
115my( $file, $usefile, $cc, $address, $bugaddress, $testaddress, $thanksaddress,
116    $filename, $messageid, $domain, $subject, $from, $verbose, $ed, $outfile,
117    $fh, $me, $body, $andcc, %REP, $ok, $thanks, $progname,
118    $Is_MSWin32, $Is_Linux, $Is_VMS, $Is_OpenBSD,
119    $report_about_module, $category, $severity,
120    %opt,
121);
122
123my $perl_version = $^V ? sprintf("%vd", $^V) : $];
124
125my $config_tag2 = "$perl_version - $Config{cf_time}";
126
127Init();
128
129if ($opt{h}) { Help(); exit; }
130if ($opt{d}) { Dump(*STDOUT); exit; }
131if (!-t STDIN && !($ok and not $opt{n})) {
132    paraprint <<"EOF";
133Please use $progname interactively. If you want to
134include a file, you can use the -f switch.
135EOF
136    die "\n";
137}
138
139Query();
140Edit() unless $usefile || ($ok and not $opt{n});
141NowWhat();
142if ($outfile) {
143    save_message_to_disk($outfile);
144} else {
145    Send();
146    if ($thanks) {
147	print "\nThank you for taking the time to send a thank-you message!\n\n";
148    } else {
149	print "\nThank you for taking the time to file a bug report!\n\n";
150    }
151}
152
153exit;
154
155sub ask_for_alternatives { # (category|severity)
156    my $name = shift;
157    my %alts = (
158	'category' => {
159	    'default' => 'core',
160	    'ok'      => 'install',
161	    # Inevitably some of these will end up in RT whatever we do:
162	    'thanks'  => 'thanks',
163	    'opts'    => [qw(core docs install library utilities)], # patch, notabug
164	},
165	'severity' => {
166	    'default' => 'low',
167	    'ok'      => 'none',
168	    'thanks'  => 'none',
169	    'opts'    => [qw(critical high medium low wishlist none)], # zero
170	},
171    );
172    die "Invalid alternative ($name) requested\n" unless grep(/^$name$/, keys %alts);
173    my $alt = "";
174    my $what = $ok || $thanks;
175    if ($what) {
176	$alt = $alts{$name}{$what};
177    } else {
178 	my @alts = @{$alts{$name}{'opts'}};
179    print "\n\n";
180	paraprint <<EOF;
181Please pick a $name from the following list:
182
183    @alts
184EOF
185	my $err = 0;
186	do {
187	    if ($err++ > 5) {
188		die "Invalid $name: aborting.\n";
189	    }
190        $alt = _prompt('', "\u$name", $alts{$name}{'default'});
191		$alt ||= $alts{$name}{'default'};
192	} while !((($alt) = grep(/^$alt/i, @alts)));
193    }
194    lc $alt;
195}
196
197sub Init {
198    # -------- Setup --------
199
200    $Is_MSWin32 = $^O eq 'MSWin32';
201    $Is_VMS = $^O eq 'VMS';
202    $Is_Linux = lc($^O) eq 'linux';
203    $Is_OpenBSD = lc($^O) eq 'openbsd';
204
205    if (!getopts("Adhva:s:b:f:F:r:e:SCc:to:n:T", \%opt)) { Help(); exit; };
206
207    # This comment is needed to notify metaconfig that we are
208    # using the $perladmin, $cf_by, and $cf_time definitions.
209
210    # -------- Configuration ---------
211
212    # perlbug address
213    $bugaddress = 'perlbug@perl.org';
214
215    # Test address
216    $testaddress = 'perlbug-test@perl.org';
217
218    # Thanks address
219    $thanksaddress = 'perl-thanks@perl.org';
220
221    if (basename ($0) =~ /^perlthanks/i) {
222	# invoked as perlthanks
223	$opt{T} = 1;
224	$opt{C} = 1; # don't send a copy to the local admin
225    }
226
227    if ($opt{T}) {
228	$thanks = 'thanks';
229    }
230
231    $progname = $thanks ? 'perlthanks' : 'perlbug';
232    # Target address
233    $address = $opt{a} || ($opt{t} ? $testaddress
234			    : $thanks ? $thanksaddress : $bugaddress);
235
236    # Users address, used in message and in From and Reply-To headers
237    $from = $opt{r} || "";
238
239    # Include verbose configuration information
240    $verbose = $opt{v} || 0;
241
242    # Subject of bug-report message
243    $subject = $opt{s} || "";
244
245    # Send a file
246    $usefile = ($opt{f} || 0);
247
248    # File to send as report
249    $file = $opt{f} || "";
250
251    # File to output to
252    $outfile = $opt{F} || "";
253
254    # Body of report
255    $body = $opt{b} || "";
256
257    # Editor
258    $ed = $opt{e} || $ENV{VISUAL} || $ENV{EDITOR} || $ENV{EDIT}
259	|| ($Is_VMS && "edit/tpu")
260	|| ($Is_MSWin32 && "notepad")
261	|| "vi";
262
263    # Not OK - provide build failure template by finessing OK report
264    if ($opt{n}) {
265	if (substr($opt{n}, 0, 2) eq 'ok' )	{
266	    $opt{o} = substr($opt{n}, 1);
267	} else {
268	    Help();
269	    exit();
270	}
271    }
272
273    # OK - send "OK" report for build on this system
274    $ok = '';
275    if ($opt{o}) {
276	if ($opt{o} eq 'k' or $opt{o} eq 'kay') {
277	    my $age = time - $patchlevel_date;
278	    if ($opt{o} eq 'k' and $age > 60 * 24 * 60 * 60 ) {
279		my $date = localtime $patchlevel_date;
280		print <<"EOF";
281"perlbug -ok" and "perlbug -nok" do not report on Perl versions which
282are more than 60 days old.  This Perl version was constructed on
283$date.  If you really want to report this, use
284"perlbug -okay" or "perlbug -nokay".
285EOF
286		exit();
287	    }
288	    # force these options
289	    unless ($opt{n}) {
290		$opt{S} = 1; # don't prompt for send
291		$opt{b} = 1; # we have a body
292		$body = "Perl reported to build OK on this system.\n";
293	    }
294	    $opt{C} = 1; # don't send a copy to the local admin
295	    $opt{s} = 1; # we have a subject line
296	    $subject = ($opt{n} ? 'Not ' : '')
297		    . "OK: perl $perl_version ${patch_tags}on"
298		    ." $::Config{'archname'} $::Config{'osvers'} $subject";
299	    $ok = 'ok';
300	} else {
301	    Help();
302	    exit();
303	}
304    }
305
306    # Possible administrator addresses, in order of confidence
307    # (Note that cf_email is not mentioned to metaconfig, since
308    # we don't really want it. We'll just take it if we have to.)
309    #
310    # This has to be after the $ok stuff above because of the way
311    # that $opt{C} is forced.
312    $cc = $opt{C} ? "" : (
313	$opt{c} || $::Config{'perladmin'}
314	|| $::Config{'cf_email'} || $::Config{'cf_by'}
315    );
316
317    if ($::HaveUtil) {
318		$domain = Mail::Util::maildomain();
319    } elsif ($Is_MSWin32) {
320		$domain = $ENV{'USERDOMAIN'};
321    } else {
322		require Sys::Hostname;
323		$domain = Sys::Hostname::hostname();
324    }
325
326    # Message-Id - rjsf
327    $messageid = "<$::Config{'version'}_${$}_".time."\@$domain>";
328
329    # My username
330    $me = $Is_MSWin32 ? $ENV{'USERNAME'}
331	    : $^O eq 'os2' ? $ENV{'USER'} || $ENV{'LOGNAME'}
332	    : eval { getpwuid($<) };	# May be missing
333
334    $from = $::Config{'cf_email'}
335       if !$from && $::Config{'cf_email'} && $::Config{'cf_by'} && $me &&
336               ($me eq $::Config{'cf_by'});
337} # sub Init
338
339sub Query {
340    # Explain what perlbug is
341    unless ($ok) {
342	if ($thanks) {
343	    paraprint <<'EOF';
344This program provides an easy way to send a thank-you message back to the
345authors and maintainers of perl.
346
347If you wish to submit a bug report, please run it without the -T flag.
348EOF
349	} else {
350	    paraprint <<"EOF";
351This program provides an easy way to create a message reporting a
352bug in the core perl distribution (along with tests or patches)
353to the volunteers who maintain perl at $address.  To send a thank-you
354note to $thanksaddress instead of a bug report, please use the -T flag.
355
356Please do not use $0 to send test messages, test whether perl
357works, or to report bugs in perl modules from CPAN.
358
359Suggestions for how to find help using Perl can be found at
360http://perldoc.perl.org/perlcommunity.html
361EOF
362	}
363    }
364
365    # Prompt for subject of message, if needed
366
367    if ($subject && TrivialSubject($subject)) {
368	$subject = '';
369    }
370
371    unless ($subject) {
372	    print
373"First of all, please provide a subject for the message.\n";
374	if ( not $thanks)  {
375	    paraprint <<EOF;
376This should be a concise description of your bug or problem
377which will help the volunteers working to improve perl to categorize
378and resolve the issue.  Be as specific and descriptive as
379you can. A subject like "perl bug" or "perl problem" will make it
380much less likely that your issue gets the attention it deserves.
381EOF
382	}
383
384	my $err = 0;
385	do {
386        $subject = _prompt('','Subject');
387	    if ($err++ == 5) {
388		if ($thanks) {
389		    $subject = 'Thanks for Perl';
390		} else {
391		    die "Aborting.\n";
392		}
393	    }
394	} while (TrivialSubject($subject));
395    }
396
397    # Prompt for return address, if needed
398    unless ($opt{r}) {
399	# Try and guess return address
400	my $guess;
401
402	$guess = $ENV{'REPLY-TO'} || $ENV{'REPLYTO'} || $ENV{'EMAIL'}
403	    || $from || '';
404
405	unless ($guess) {
406		# move $domain to where we can use it elsewhere
407        if ($domain) {
408		if ($Is_VMS && !$::Config{'d_socket'}) {
409		    $guess = "$domain\:\:$me";
410		} else {
411		    $guess = "$me\@$domain" if $domain;
412		}
413	    }
414	}
415
416	if ($guess) {
417	    unless ($ok) {
418		paraprint <<EOF;
419Perl's developers may need your email address to contact you for
420further information about your issue or to inform you when it is
421resolved.  If the default shown is not your email address, please
422correct it.
423EOF
424	    }
425	} else {
426	    paraprint <<EOF;
427Please enter your full internet email address so that Perl's
428developers can contact you with questions about your issue or to
429inform you that it has been resolved.
430EOF
431	}
432
433	if ($ok && $guess) {
434	    # use it
435	    $from = $guess;
436	} else {
437	    # verify it
438        $from = _prompt('','Your address',$guess);
439	    $from = $guess if $from eq '';
440	}
441    }
442
443    if ($from eq $cc or $me eq $cc) {
444	# Try not to copy ourselves
445	$cc = "yourself";
446    }
447
448    # Prompt for administrator address, unless an override was given
449    if( !$opt{C} and !$opt{c} ) {
450	my $description =  <<EOF;
451$0 can send a copy of this report to your local perl
452administrator.  If the address below is wrong, please correct it,
453or enter 'none' or 'yourself' to not send a copy.
454EOF
455	my $entry = _prompt($description, "Local perl administrator", $cc);
456
457	if ($entry ne "") {
458	    $cc = $entry;
459	    $cc = '' if $me eq $cc;
460	}
461    }
462
463    $cc = '' if $cc =~ /^(none|yourself|me|myself|ourselves)$/i;
464    if ($cc) {
465        $andcc = " and $cc"
466    } else {
467        $andcc = ''
468    }
469
470    # Prompt for editor, if no override is given
471editor:
472    unless ($opt{e} || $opt{f} || $opt{b}) {
473
474    my $description;
475
476	chomp (my $common_end = <<"EOF");
477You will probably want to use a text editor to enter the body of
478your report. If "$ed" is the editor you want to use, then just press
479Enter, otherwise type in the name of the editor you would like to
480use.
481
482If you have already composed the body of your report, you may enter
483"file", and $0 will prompt you to enter the name of the file
484containing your report.
485EOF
486
487	if ($thanks) {
488	    $description = <<"EOF";
489It's now time to compose your thank-you message.
490
491Some information about your local perl configuration will automatically
492be included at the end of your message, because we're curious about
493the different ways that people build and use perl. If you'd rather
494not share this information, you're welcome to delete it.
495
496$common_end
497EOF
498	} else {
499	    $description =  <<"EOF";
500It's now time to compose your bug report. Try to make the report
501concise but descriptive. Please include any detail which you think
502might be relevant or might help the volunteers working to improve
503perl. If you are reporting something that does not work as you think
504it should, please try to include examples of the actual result and of
505what you expected.
506
507Some information about your local perl configuration will automatically
508be included at the end of your report. If you are using an unusual
509version of perl, it would be useful if you could confirm that you
510can replicate the problem on a standard build of perl as well.
511
512$common_end
513EOF
514	}
515
516    my $entry = _prompt($description, "Editor", $ed);
517	$usefile = 0;
518	if ($entry eq "file") {
519	    $usefile = 1;
520	} elsif ($entry ne "") {
521	    $ed = $entry;
522	}
523    }
524    if ($::HaveCoreList && !$ok && !$thanks) {
525	my $description =  <<EOF;
526If your bug is about a Perl module rather than a core language
527feature, please enter its name here. If it's not, just hit Enter
528to skip this question.
529EOF
530
531    my $entry = '';
532	while ($entry eq '') {
533        $entry = _prompt($description, 'Module');
534	    my $first_release = Module::CoreList->first_release($entry);
535	    if ($entry and not $first_release) {
536		paraprint <<EOF;
537$entry is not a "core" Perl module. Please check that you entered
538its name correctly. If it is correct, quit this program, try searching
539for $entry on http://rt.cpan.org, and report your issue there.
540EOF
541
542            $entry = '';
543	} elsif (my $bug_tracker = $Module::CoreList::bug_tracker{$entry}) {
544		paraprint <<"EOF";
545$entry included with core Perl is copied directly from the CPAN distribution.
546Please report bugs in $entry directly to its maintainers using $bug_tracker
547EOF
548            $entry = '';
549        } elsif ($entry) {
550	        $category ||= 'library';
551	        $report_about_module = $entry;
552            last;
553        } else {
554            last;
555        }
556	}
557    }
558
559    # Prompt for category of bug
560    $category ||= ask_for_alternatives('category');
561
562    # Prompt for severity of bug
563    $severity ||= ask_for_alternatives('severity');
564
565    # Generate scratch file to edit report in
566    $filename = filename();
567
568    # Prompt for file to read report from, if needed
569    if ($usefile and !$file) {
570filename:
571	my $description = <<EOF;
572What is the name of the file that contains your report?
573EOF
574	my $entry = _prompt($description, "Filename");
575
576	if ($entry eq "") {
577	    paraprint <<EOF;
578It seems you didn't enter a filename. Please choose to use a text
579editor or enter a filename.
580EOF
581	    goto editor;
582	}
583
584	unless (-f $entry and -r $entry) {
585	    paraprint <<EOF;
586'$entry' doesn't seem to be a readable file.  You may have mistyped
587its name or may not have permission to read it.
588
589If you don't want to use a file as the content of your report, just
590hit Enter and you'll be able to select a text editor instead.
591EOF
592	    goto filename;
593	}
594	$file = $entry;
595    }
596
597    # Generate report
598    open(REP,">$filename") or die "Unable to create report file '$filename': $!\n";
599    my $reptype = !$ok ? ($thanks ? 'thank-you' : 'bug')
600	: $opt{n} ? "build failure" : "success";
601
602    print REP <<EOF;
603This is a $reptype report for perl from $from,
604generated with the help of perlbug $Version running under perl $perl_version.
605
606EOF
607
608    if ($body) {
609	print REP $body;
610    } elsif ($usefile) {
611	open(F, "<$file")
612		or die "Unable to read report file from '$file': $!\n";
613	while (<F>) {
614	    print REP $_
615	}
616	close(F) or die "Error closing '$file': $!";
617    } else {
618	if ($thanks) {
619	    print REP <<'EOF';
620
621-----------------------------------------------------------------
622[Please enter your thank-you message here]
623
624
625
626[You're welcome to delete anything below this line]
627-----------------------------------------------------------------
628EOF
629	} else {
630	    print REP <<'EOF';
631
632-----------------------------------------------------------------
633[Please describe your issue here]
634
635
636
637[Please do not change anything below this line]
638-----------------------------------------------------------------
639EOF
640	}
641    }
642    Dump(*REP);
643    close(REP) or die "Error closing report file: $!";
644
645    # Set up an initial report fingerprint so we can compare it later
646    _fingerprint_lines_in_report();
647
648} # sub Query
649
650sub Dump {
651    local(*OUT) = @_;
652
653    # these won't have been set if run with -d
654    $category ||= 'core';
655    $severity ||= 'low';
656
657    print OUT <<EFF;
658---
659Flags:
660    category=$category
661    severity=$severity
662EFF
663
664    if ($report_about_module ) {
665        print OUT <<EFF;
666    module=$report_about_module
667EFF
668    }
669    if ($opt{A}) {
670	print OUT <<EFF;
671    ack=no
672EFF
673    }
674    print OUT <<EFF;
675---
676EFF
677    print OUT "This perlbug was built using Perl $config_tag1\n",
678	    "It is being executed now by  Perl $config_tag2.\n\n"
679	if $config_tag2 ne $config_tag1;
680
681    print OUT <<EOF;
682Site configuration information for perl $perl_version:
683
684EOF
685    if ($::Config{cf_by} and $::Config{cf_time}) {
686	print OUT "Configured by $::Config{cf_by} at $::Config{cf_time}.\n\n";
687    }
688    print OUT Config::myconfig;
689
690    if (@patches) {
691	print OUT join "\n    ", "Locally applied patches:", @patches;
692	print OUT "\n";
693    };
694
695    print OUT <<EOF;
696
697---
698\@INC for perl $perl_version:
699EOF
700    for my $i (@INC) {
701	print OUT "    $i\n";
702    }
703
704    print OUT <<EOF;
705
706---
707Environment for perl $perl_version:
708EOF
709    my @env =
710        qw(PATH LD_LIBRARY_PATH LANG PERL_BADLANG SHELL HOME LOGDIR LANGUAGE);
711    push @env, $Config{ldlibpthname} if $Config{ldlibpthname} ne '';
712    push @env, grep /^(?:PERL|LC_|LANG|CYGWIN)/, keys %ENV;
713    my %env;
714    @env{@env} = @env;
715    for my $env (sort keys %env) {
716	print OUT "    $env",
717		exists $ENV{$env} ? "=$ENV{$env}" : ' (unset)',
718		"\n";
719    }
720    if ($verbose) {
721	print OUT "\nComplete configuration data for perl $perl_version:\n\n";
722	my $value;
723	foreach (sort keys %::Config) {
724	    $value = $::Config{$_};
725	    $value = '' unless defined $value;
726	    $value =~ s/'/\\'/g;
727	    print OUT "$_='$value'\n";
728	}
729    }
730} # sub Dump
731
732sub Edit {
733    # Edit the report
734    if ($usefile || $body) {
735	my $description = "Please make sure that the name of the editor you want to use is correct.";
736	my $entry = _prompt($description, 'Editor', $ed);
737	$ed = $entry unless $entry eq '';
738    }
739
740    _edit_file($ed);
741}
742
743sub _edit_file {
744    my $editor = shift;
745
746    my $report_written = 0;
747
748    while ( !$report_written ) {
749        my $exit_status = system("$editor $filename");
750        if ($exit_status) {
751            my $desc = <<EOF;
752The editor you chose ('$editor') could not be run!
753
754If you mistyped its name, please enter it now, otherwise just press Enter.
755EOF
756            my $entry = _prompt( $desc, 'Editor', $editor );
757            if ( $entry ne "" ) {
758                $editor = $entry;
759                next;
760            } else {
761                paraprint <<EOF;
762You may want to save your report to a file, so you can edit and
763mail it later.
764EOF
765                return;
766            }
767        }
768        return if ( $ok and not $opt{n} ) || $body;
769
770        # Check that we have a report that has some, eh, report in it.
771
772        unless ( _fingerprint_lines_in_report() ) {
773            my $description = <<EOF;
774It looks like you didn't enter a report. You may [r]etry your edit
775or [c]ancel this report.
776EOF
777            my $action = _prompt( $description, "Action (Retry/Cancel) " );
778            if ( $action =~ /^[re]/i ) {    # <R>etry <E>dit
779                next;
780            } elsif ( $action =~ /^[cq]/i ) {    # <C>ancel, <Q>uit
781                Cancel();                        # cancel exits
782            }
783        }
784        # Ok. the user did what they needed to;
785        return;
786
787    }
788}
789
790
791sub Cancel {
792    1 while unlink($filename);  # remove all versions under VMS
793    print "\nQuitting without sending your message.\n";
794    exit(0);
795}
796
797sub NowWhat {
798    # Report is done, prompt for further action
799    if( !$opt{S} ) {
800	while(1) {
801	    my $menu = <<EOF;
802
803
804You have finished composing your message. At this point, you have
805a few options. You can:
806
807    * [Se]nd the message to $address$andcc,
808    * [D]isplay the message on the screen,
809    * [R]e-edit the message
810    * Display or change the message's [su]bject
811    * Save the message to a [f]ile to mail at another time
812    * [Q]uit without sending a message
813
814EOF
815      retry:
816        print $menu;
817	    my $action =  _prompt('', "Action (Send/Display/Edit/Subject/Save to File)");;
818        print "\n";
819	    if ($action =~ /^(f|sa)/i) { # <F>ile/<Sa>ve
820            if ( SaveMessage() ) { exit }
821	    } elsif ($action =~ /^(d|l|sh)/i ) { # <D>isplay, <L>ist, <Sh>ow
822		# Display the message
823		open(REP, "<$filename") or die "Couldn't open file '$filename': $!\n";
824		while (<REP>) { print $_ }
825		close(REP) or die "Error closing report file '$filename': $!";
826	    } elsif ($action =~ /^su/i) { # <Su>bject
827		my $reply = _prompt( "Subject: $subject", "If the above subject is fine, press Enter. Otherwise, type a replacement now\nSubject");
828		if ($reply ne '') {
829		    unless (TrivialSubject($reply)) {
830			$subject = $reply;
831			print "Subject: $subject\n";
832		    }
833		}
834	    } elsif ($action =~ /^se/i) { # <S>end
835		# Send the message
836		my $reply =  _prompt( "Are you certain you want to send this message?", 'Please type "yes" if you are','no');
837		if ($reply =~ /^yes$/) {
838		    last;
839		} else {
840		    paraprint <<EOF;
841You didn't type "yes", so your message has not yet been sent.
842EOF
843		}
844	    } elsif ($action =~ /^[er]/i) { # <E>dit, <R>e-edit
845		# edit the message
846		Edit();
847	    } elsif ($action =~ /^[qc]/i) { # <C>ancel, <Q>uit
848		Cancel();
849	    } elsif ($action =~ /^s/i) {
850		paraprint <<EOF;
851The command you entered was ambiguous. Please type "send", "save" or "subject".
852EOF
853	    }
854	}
855    }
856} # sub NowWhat
857
858sub TrivialSubject {
859    my $subject = shift;
860    if ($subject =~
861	/^(y(es)?|no?|help|perl( (bug|problem))?|bug|problem)$/i ||
862	length($subject) < 4 ||
863	$subject !~ /\s/) {
864	print "\nThe subject you entered wasn't very descriptive. Please try again.\n\n";
865        return 1;
866    } else {
867	return 0;
868    }
869}
870
871sub SaveMessage {
872    my $file_save = $outfile || "$progname.rep";
873    my $file = _prompt( '', "Name of file to save message in", $file_save );
874    save_message_to_disk($file) || return undef;
875    print "\n";
876    paraprint <<EOF;
877A copy of your message has been saved in '$file' for you to
878send to '$address' with your normal mail client.
879EOF
880}
881
882sub Send {
883
884    # Message has been accepted for transmission -- Send the message
885
886    # on linux certain "mail" implementations won't accept the subject
887    # as "~s subject" and thus the Subject header will be corrupted
888    # so don't use Mail::Send to be safe
889    eval {
890        if ( $::HaveSend && !$Is_Linux && !$Is_OpenBSD ) {
891            _send_message_mailsend();
892        } elsif ($Is_VMS) {
893            _send_message_vms();
894        } else {
895            _send_message_sendmail();
896        }
897    };
898
899    if ( my $error = $@ ) {
900        paraprint <<EOF;
901$0 has detected an error while trying to send your message: $error.
902
903Your message may not have been sent. You will now have a chance to save a copy to disk.
904EOF
905        SaveMessage();
906        return;
907    }
908
909    1 while unlink($filename);    # remove all versions under VMS
910}    # sub Send
911
912sub Help {
913    print <<EOF;
914
915This program is designed to help you generate and send bug reports
916(and thank-you notes) about perl5 and the modules which ship with it.
917
918In most cases, you can just run "$0" interactively from a command
919line without any special arguments and follow the prompts.
920
921Advanced usage:
922
923$0  [-v] [-a address] [-s subject] [-b body | -f inpufile ] [ -F outputfile ]
924    [-r returnaddress] [-e editor] [-c adminaddress | -C] [-S] [-t] [-h]
925$0  [-v] [-r returnaddress] [-A] [-ok | -okay | -nok | -nokay]
926
927
928Options:
929
930  -v    Include Verbose configuration data in the report
931  -f    File containing the body of the report. Use this to
932        quickly send a prepared message.
933  -F    File to output the resulting mail message to, instead of mailing.
934  -S    Send without asking for confirmation.
935  -a    Address to send the report to. Defaults to '$address'.
936  -c    Address to send copy of report to. Defaults to '$cc'.
937  -C    Don't send copy to administrator.
938  -s    Subject to include with the message. You will be prompted
939        if you don't supply one on the command line.
940  -b    Body of the report. If not included on the command line, or
941        in a file with -f, you will get a chance to edit the message.
942  -r    Your return address. The program will ask you to confirm
943        this if you don't give it here.
944  -e    Editor to use.
945  -t    Test mode. The target address defaults to '$testaddress'.
946  -T    Thank-you mode. The target address defaults to '$thanksaddress'.
947  -d    Data mode.  This prints out your configuration data, without mailing
948        anything. You can use this with -v to get more complete data.
949  -A    Don't send a bug received acknowledgement to the return address.
950  -ok   Report successful build on this system to perl porters
951        (use alone or with -v). Only use -ok if *everything* was ok:
952        if there were *any* problems at all, use -nok.
953  -okay As -ok but allow report from old builds.
954  -nok  Report unsuccessful build on this system to perl porters
955        (use alone or with -v). You must describe what went wrong
956        in the body of the report which you will be asked to edit.
957  -nokay As -nok but allow report from old builds.
958  -h    Print this help message.
959
960EOF
961}
962
963sub filename {
964    if ($::HaveTemp) {
965	# Good. Use a secure temp file
966	my ($fh, $filename) = File::Temp::tempfile(UNLINK => 1);
967	close($fh);
968	return $filename;
969    } else {
970	# Bah. Fall back to doing things less securely.
971	my $dir = File::Spec->tmpdir();
972	$filename = "bugrep0$$";
973	$filename++ while -e File::Spec->catfile($dir, $filename);
974	$filename = File::Spec->catfile($dir, $filename);
975    }
976}
977
978sub paraprint {
979    my @paragraphs = split /\n{2,}/, "@_";
980    for (@paragraphs) {   # implicit local $_
981	s/(\S)\s*\n/$1 /g;
982	write;
983	print "\n";
984    }
985}
986
987sub _prompt {
988    my ($explanation, $prompt, $default) = (@_);
989    if ($explanation) {
990        print "\n\n";
991        paraprint $explanation;
992    }
993    print $prompt. ($default ? " [$default]" :''). ": ";
994	my $result = scalar(<>);
995    chomp($result);
996	$result =~ s/^\s*(.*?)\s*$/$1/s;
997    if ($default && $result eq '') {
998        return $default;
999    } else {
1000        return $result;
1001    }
1002}
1003
1004sub _build_header {
1005    my %attr = (@_);
1006
1007    my $head = '';
1008    for my $header (keys %attr) {
1009        $head .= "$header: ".$attr{$header}."\n";
1010    }
1011    return $head;
1012}
1013
1014sub _message_headers {
1015    my %headers = ( To => $address, Subject => $subject );
1016    $headers{'Cc'}         = $cc        if ($cc);
1017    $headers{'Message-Id'} = $messageid if ($messageid);
1018    $headers{'Reply-To'}   = $from      if ($from);
1019    $headers{'From'}       = $from      if ($from);
1020    return \%headers;
1021}
1022
1023sub build_complete_message {
1024    my $content = _build_header(%{_message_headers()}) . "\n\n";
1025    open( REP, "<$filename" ) or die "Couldn't open file '$filename': $!\n";
1026    while (<REP>) { $content .= $_; }
1027    close(REP) or die "Error closing report file '$filename': $!";
1028    return $content;
1029}
1030
1031sub save_message_to_disk {
1032    my $file = shift;
1033
1034	    open OUTFILE, ">$file" or do { warn  "Couldn't open '$file': $!\n"; return undef};
1035        print OUTFILE build_complete_message();
1036        close(OUTFILE) or do { warn  "Error closing $file: $!"; return undef };
1037	    print "\nMessage saved.\n";
1038        return 1;
1039}
1040
1041sub _send_message_vms {
1042    if (   ( $address =~ /@/ and $address !~ /^\w+%"/ )
1043        or ( $cc =~ /@/ and $cc !~ /^\w+%"/ ) ) {
1044        my $prefix;
1045        foreach ( qw[ IN MX SMTP UCX PONY WINS ], '' ) {
1046            $prefix = "$_%", last if $ENV{"MAIL\$PROTOCOL_$_"};
1047        }
1048        $address = qq[${prefix}"$address"] unless $address =~ /^\w+%"/;
1049        $cc = qq[${prefix}"$cc"] unless !$cc || $cc =~ /^\w+%"/;
1050    }
1051    $subject =~ s/"/""/g;
1052    $address =~ s/"/""/g;
1053    $cc      =~ s/"/""/g;
1054    my $sts = system(qq[mail/Subject="$subject" $filename. "$address","$cc"]);
1055    if ($sts) {
1056        die "Can't spawn off mail (leaving bug report in $filename): $sts";
1057    }
1058}
1059
1060sub _send_message_mailsend {
1061    my $msg = Mail::Send->new();
1062    my %headers = %{_message_headers()};
1063    for my $key ( keys %headers) {
1064        $msg->add($key => $headers{$key});
1065    }
1066
1067    $fh = $msg->open;
1068    open(REP, "<$filename") or die "Couldn't open '$filename': $!\n";
1069    while (<REP>) { print $fh $_ }
1070    close(REP) or die "Error closing $filename: $!";
1071    $fh->close or die "Error sending mail: $!";
1072
1073    print "\nMessage sent.\n";
1074}
1075
1076sub _probe_for_sendmail {
1077    my $sendmail = "";
1078    for (qw(/usr/lib/sendmail /usr/sbin/sendmail /usr/ucblib/sendmail)) {
1079        $sendmail = $_, last if -e $_;
1080    }
1081    if ( $^O eq 'os2' and $sendmail eq "" ) {
1082        my $path = $ENV{PATH};
1083        $path =~ s:\\:/:;
1084        my @path = split /$Config{'path_sep'}/, $path;
1085        for (@path) {
1086            $sendmail = "$_/sendmail",     last if -e "$_/sendmail";
1087            $sendmail = "$_/sendmail.exe", last if -e "$_/sendmail.exe";
1088        }
1089    }
1090    return $sendmail;
1091}
1092
1093sub _send_message_sendmail {
1094    my $sendmail = _probe_for_sendmail();
1095    unless ($sendmail) {
1096        my $message_start = !$Is_Linux && !$Is_OpenBSD ? <<'EOT' : <<'EOT';
1097It appears that there is no program which looks like "sendmail" on
1098your system and that the Mail::Send library from CPAN isn't available.
1099EOT
1100It appears that there is no program which looks like "sendmail" on
1101your system.
1102EOT
1103        paraprint(<<"EOF"), die "\n";
1104$message_start
1105Because of this, there's no easy way to automatically send your
1106message.
1107
1108A copy of your message has been saved in '$filename' for you to
1109send to '$address' with your normal mail client.
1110EOF
1111    }
1112
1113    open( SENDMAIL, "|-", $sendmail, "-t", "-oi", "-f", $from )
1114        || die "'|$sendmail -t -oi -f $from' failed: $!";
1115    print SENDMAIL build_complete_message();
1116    if ( close(SENDMAIL) ) {
1117        print "\nMessage sent\n";
1118    } else {
1119        warn "\nSendmail returned status '", $? >> 8, "'\n";
1120    }
1121}
1122
1123
1124
1125# a strange way to check whether any significant editing
1126# has been done: check whether any new non-empty lines
1127# have been added.
1128
1129sub _fingerprint_lines_in_report {
1130    my $new_lines = 0;
1131    # read in the report template once so that
1132    # we can track whether the user does any editing.
1133    # yes, *all* whitespace is ignored.
1134
1135    open(REP, "<$filename") or die "Unable to open report file '$filename': $!\n";
1136    while (my $line = <REP>) {
1137        $line =~ s/\s+//g;
1138        $new_lines++ if (!$REP{$line});
1139
1140    }
1141    close(REP) or die "Error closing report file '$filename': $!";
1142    # returns the number of lines with content that wasn't there when last we looked
1143    return $new_lines;
1144}
1145
1146
1147
1148format STDOUT =
1149^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
1150$_
1151.
1152
1153__END__
1154
1155=head1 NAME
1156
1157perlbug - how to submit bug reports on Perl
1158
1159=head1 SYNOPSIS
1160
1161B<perlbug>
1162
1163B<perlbug> S<[ B<-v> ]> S<[ B<-a> I<address> ]> S<[ B<-s> I<subject> ]>
1164S<[ B<-b> I<body> | B<-f> I<inputfile> ]> S<[ B<-F> I<outputfile> ]>
1165S<[ B<-r> I<returnaddress> ]>
1166S<[ B<-e> I<editor> ]> S<[ B<-c> I<adminaddress> | B<-C> ]>
1167S<[ B<-S> ]> S<[ B<-t> ]>  S<[ B<-d> ]>  S<[ B<-A> ]>  S<[ B<-h> ]> S<[ B<-T> ]>
1168
1169B<perlbug> S<[ B<-v> ]> S<[ B<-r> I<returnaddress> ]>
1170 S<[ B<-A> ]> S<[ B<-ok> | B<-okay> | B<-nok> | B<-nokay> ]>
1171
1172=head1 DESCRIPTION
1173
1174
1175This program is designed to help you generate and send bug reports
1176(and thank-you notes) about perl5 and the modules which ship with it.
1177
1178In most cases, you can just run it interactively from a command
1179line without any special arguments and follow the prompts.
1180
1181If you have found a bug with a non-standard port (one that was not
1182part of the I<standard distribution>), a binary distribution, or a
1183non-core module (such as Tk, DBI, etc), then please see the
1184documentation that came with that distribution to determine the
1185correct place to report bugs.
1186
1187If you are unable to send your report using B<perlbug> (most likely
1188because your system doesn't have a way to send mail that perlbug
1189recognizes), you may be able to use this tool to compose your report
1190and save it to a file which you can then send to B<perlbug@perl.org>
1191using your regular mail client.
1192
1193In extreme cases, B<perlbug> may not work well enough on your system
1194to guide you through composing a bug report. In those cases, you
1195may be able to use B<perlbug -d> to get system configuration
1196information to include in a manually composed bug report to
1197B<perlbug@perl.org>.
1198
1199
1200When reporting a bug, please run through this checklist:
1201
1202=over 4
1203
1204=item What version of Perl you are running?
1205
1206Type C<perl -v> at the command line to find out.
1207
1208=item Are you running the latest released version of perl?
1209
1210Look at http://www.perl.org/ to find out.  If you are not using the
1211latest released version, please try to replicate your bug on the
1212latest stable release.
1213
1214Note that reports about bugs in old versions of Perl, especially
1215those which indicate you haven't also tested the current stable
1216release of Perl, are likely to receive less attention from the
1217volunteers who build and maintain Perl than reports about bugs in
1218the current release.
1219
1220This tool isn't appropriate for reporting bugs in any version
1221prior to Perl 5.0.
1222
1223=item Are you sure what you have is a bug?
1224
1225A significant number of the bug reports we get turn out to be
1226documented features in Perl.  Make sure the issue you've run into
1227isn't intentional by glancing through the documentation that comes
1228with the Perl distribution.
1229
1230Given the sheer volume of Perl documentation, this isn't a trivial
1231undertaking, but if you can point to documentation that suggests
1232the behaviour you're seeing is I<wrong>, your issue is likely to
1233receive more attention. You may want to start with B<perldoc>
1234L<perltrap> for pointers to common traps that new (and experienced)
1235Perl programmers run into.
1236
1237If you're unsure of the meaning of an error message you've run
1238across, B<perldoc> L<perldiag> for an explanation.  If the message
1239isn't in perldiag, it probably isn't generated by Perl.  You may
1240have luck consulting your operating system documentation instead.
1241
1242If you are on a non-UNIX platform B<perldoc> L<perlport>, as some
1243features may be unimplemented or work differently.
1244
1245You may be able to figure out what's going wrong using the Perl
1246debugger.  For information about how to use the debugger B<perldoc>
1247L<perldebug>.
1248
1249=item Do you have a proper test case?
1250
1251The easier it is to reproduce your bug, the more likely it will be
1252fixed -- if nobody can duplicate your problem, it probably won't be
1253addressed.
1254
1255A good test case has most of these attributes: short, simple code;
1256few dependencies on external commands, modules, or libraries; no
1257platform-dependent code (unless it's a platform-specific bug);
1258clear, simple documentation.
1259
1260A good test case is almost always a good candidate to be included in
1261Perl's test suite.  If you have the time, consider writing your test case so
1262that it can be easily included into the standard test suite.
1263
1264=item Have you included all relevant information?
1265
1266Be sure to include the B<exact> error messages, if any.
1267"Perl gave an error" is not an exact error message.
1268
1269If you get a core dump (or equivalent), you may use a debugger
1270(B<dbx>, B<gdb>, etc) to produce a stack trace to include in the bug
1271report.
1272
1273NOTE: unless your Perl has been compiled with debug info
1274(often B<-g>), the stack trace is likely to be somewhat hard to use
1275because it will most probably contain only the function names and not
1276their arguments.  If possible, recompile your Perl with debug info and
1277reproduce the crash and the stack trace.
1278
1279=item Can you describe the bug in plain English?
1280
1281The easier it is to understand a reproducible bug, the more likely
1282it will be fixed.  Any insight you can provide into the problem
1283will help a great deal.  In other words, try to analyze the problem
1284(to the extent you can) and report your discoveries.
1285
1286=item Can you fix the bug yourself?
1287
1288A bug report which I<includes a patch to fix it> will almost
1289definitely be fixed.  When sending a patch, please use the C<diff>
1290program with the C<-u> option to generate "unified" diff files.
1291Bug reports with patches are likely to receive significantly more
1292attention and interest than those without patches.
1293
1294Your patch may be returned with requests for changes, or requests for more
1295detailed explanations about your fix.
1296
1297Here are a few hints for creating high-quality patches:
1298
1299Make sure the patch is not reversed (the first argument to diff is
1300typically the original file, the second argument your changed file).
1301Make sure you test your patch by applying it with the C<patch>
1302program before you send it on its way.  Try to follow the same style
1303as the code you are trying to patch.  Make sure your patch really
1304does work (C<make test>, if the thing you're patching is covered
1305by Perl's test suite).
1306
1307=item Can you use C<perlbug> to submit the report?
1308
1309B<perlbug> will, amongst other things, ensure your report includes
1310crucial information about your version of perl.  If C<perlbug> is
1311unable to mail your report after you have typed it in, you may have
1312to compose the message yourself, add the output produced by C<perlbug
1313-d> and email it to B<perlbug@perl.org>.  If, for some reason, you
1314cannot run C<perlbug> at all on your system, be sure to include the
1315entire output produced by running C<perl -V> (note the uppercase V).
1316
1317Whether you use C<perlbug> or send the email manually, please make
1318your Subject line informative.  "a bug" is not informative.  Neither
1319is "perl crashes" nor is "HELP!!!".  These don't help.  A compact
1320description of what's wrong is fine.
1321
1322=item Can you use C<perlbug> to submit a thank-you note?
1323
1324Yes, you can do this by either using the C<-T> option.
1325Thank-you notes are good. It makes people
1326smile.
1327
1328=back
1329
1330Having done your bit, please be prepared to wait, to be told the
1331bug is in your code, or possibly to get no reply at all.  The
1332volunteers who maintain Perl are busy folks, so if your problem is
1333an obvious bug in your own code, is difficult to understand or is
1334a duplicate of an existing report, you may not receive a personal
1335reply.
1336
1337If it is important to you that your bug be fixed, do monitor the
1338perl5-porters@perl.org mailing list and the commit logs to development
1339versions of Perl, and encourage the maintainers with kind words or
1340offers of frosty beverages.  (Please do be kind to the maintainers.
1341Harassing or flaming them is likely to have the opposite effect of
1342the one you want.)
1343
1344Feel free to update the ticket about your bug on http://rt.perl.org
1345if a new version of Perl is released and your bug is still present.
1346
1347=head1 OPTIONS
1348
1349=over 8
1350
1351=item B<-a>
1352
1353Address to send the report to.  Defaults to B<perlbug@perl.org>.
1354
1355=item B<-A>
1356
1357Don't send a bug received acknowledgement to the reply address.
1358Generally it is only a sensible to use this option if you are a
1359perl maintainer actively watching perl porters for your message to
1360arrive.
1361
1362=item B<-b>
1363
1364Body of the report.  If not included on the command line, or
1365in a file with B<-f>, you will get a chance to edit the message.
1366
1367=item B<-C>
1368
1369Don't send copy to administrator.
1370
1371=item B<-c>
1372
1373Address to send copy of report to.  Defaults to the address of the
1374local perl administrator (recorded when perl was built).
1375
1376=item B<-d>
1377
1378Data mode (the default if you redirect or pipe output).  This prints out
1379your configuration data, without mailing anything.  You can use this
1380with B<-v> to get more complete data.
1381
1382=item B<-e>
1383
1384Editor to use.
1385
1386=item B<-f>
1387
1388File containing the body of the report.  Use this to quickly send a
1389prepared message.
1390
1391=item B<-F>
1392
1393File to output the results to instead of sending as an email. Useful
1394particularly when running perlbug on a machine with no direct internet
1395connection.
1396
1397=item B<-h>
1398
1399Prints a brief summary of the options.
1400
1401=item B<-ok>
1402
1403Report successful build on this system to perl porters. Forces B<-S>
1404and B<-C>. Forces and supplies values for B<-s> and B<-b>. Only
1405prompts for a return address if it cannot guess it (for use with
1406B<make>). Honors return address specified with B<-r>.  You can use this
1407with B<-v> to get more complete data.   Only makes a report if this
1408system is less than 60 days old.
1409
1410=item B<-okay>
1411
1412As B<-ok> except it will report on older systems.
1413
1414=item B<-nok>
1415
1416Report unsuccessful build on this system.  Forces B<-C>.  Forces and
1417supplies a value for B<-s>, then requires you to edit the report
1418and say what went wrong.  Alternatively, a prepared report may be
1419supplied using B<-f>.  Only prompts for a return address if it
1420cannot guess it (for use with B<make>). Honors return address
1421specified with B<-r>.  You can use this with B<-v> to get more
1422complete data.  Only makes a report if this system is less than 60
1423days old.
1424
1425=item B<-nokay>
1426
1427As B<-nok> except it will report on older systems.
1428
1429=item B<-r>
1430
1431Your return address.  The program will ask you to confirm its default
1432if you don't use this option.
1433
1434=item B<-S>
1435
1436Send without asking for confirmation.
1437
1438=item B<-s>
1439
1440Subject to include with the message.  You will be prompted if you don't
1441supply one on the command line.
1442
1443=item B<-t>
1444
1445Test mode.  The target address defaults to B<perlbug-test@perl.org>.
1446
1447=item B<-T>
1448
1449Send a thank-you note instead of a bug report.
1450
1451=item B<-v>
1452
1453Include verbose configuration data in the report.
1454
1455=back
1456
1457=head1 AUTHORS
1458
1459Kenneth Albanowski (E<lt>kjahds@kjahds.comE<gt>), subsequently
1460I<doc>tored by Gurusamy Sarathy (E<lt>gsar@activestate.comE<gt>),
1461Tom Christiansen (E<lt>tchrist@perl.comE<gt>), Nathan Torkington
1462(E<lt>gnat@frii.comE<gt>), Charles F. Randall (E<lt>cfr@pobox.comE<gt>),
1463Mike Guy (E<lt>mjtg@cam.ac.ukE<gt>), Dominic Dunlop
1464(E<lt>domo@computer.orgE<gt>), Hugo van der Sanden (E<lt>hv@crypt.orgE<gt>),
1465Jarkko Hietaniemi (E<lt>jhi@iki.fiE<gt>), Chris Nandor
1466(E<lt>pudge@pobox.comE<gt>), Jon Orwant (E<lt>orwant@media.mit.eduE<gt>,
1467Richard Foley (E<lt>richard.foley@rfi.netE<gt>), and Jesse Vincent
1468(E<lt>jesse@bestpractical.comE<gt>).
1469
1470=head1 SEE ALSO
1471
1472perl(1), perldebug(1), perldiag(1), perlport(1), perltrap(1),
1473diff(1), patch(1), dbx(1), gdb(1)
1474
1475=head1 BUGS
1476
1477None known (guess what must have been used to report them?)
1478
1479=cut
1480
1481!NO!SUBS!
1482
1483close OUT or die "Can't close $file: $!";
1484chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
1485exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
1486chdir $origdir;
1487