3 # Copyright (C) 2004, The Perl Foundation.
7 eval 'exec perl -w -S $0 ${1+"$@"}'
8 if $running_under_some_shell;
10 $^W
= 1; # Set warnings;
18 my $VERSION = "0.6.1";
20 # These are the standard addresses for reporting bugs.
22 ( bug
=> 'parrotbug@parrotcode.org',
23 ok
=> 'parrotstatus-ok@parrotcode.org',
24 nok
=> 'parrotstatus-nok@parrotcode.org',
27 my $parrotdir = File
::Spec
->curdir();
28 my ( %opts, %parrot, %report );
29 my ( $editor, $user, $domain, $msgid, $tmpfile );
30 my ( $is_linux, $is_macos, $is_mswin32, $is_os2, $is_vms );
31 my @categories = qw
[ core docs install library utilities languages
];
32 my @severities = qw
[ critical high medium low wishlist none
];
35 #------------------------------------------------------------#
39 help
() if $opts{help
};
40 version
() if $opts{version
};
41 explain_parrotbug
() unless $opts{quiet
};
49 # Explain what C<parrotbug> is.
50 sub explain_parrotbug
{
53 This program provides an easy way to create a message reporting a bug
54 in parrot, and e-mail it to the parrot developers.
56 It is *NOT* intended for:
57 - sending test messages,
58 - or reporting bugs in languages targetting parrot,
59 - or reporting bugs in some library bindings for parrot,
60 - or simply verifying that parrot works.
62 It is *ONLY* a mean of reporting verifiable problems with the core
63 parrot distribution, and any solutions to such problems, to parrot
66 If you're just looking for help with parrot, subscribe to the parrot
67 mailing list, parrot-porters<at>perl.org.
77 #------------------------------------------------------------#
80 # Generate random filename to edit report.
81 sub generate_filename
{
82 my $dir = File
::Spec
->tmpdir();
83 my $filename = "bugrep0$$";
84 $filename++ while -e File
::Spec
->catfile($dir, $filename);
85 $filename = File
::Spec
->catfile($dir, $filename);
90 # Check whether a subject is trivial. A subject is not considered trivial
91 # if it's an ok or a nok report.
92 # Return 1 if trivial, 0 otherwise (subject acceptable).
96 return 0 if $opts{ok
} || $opts{nok
};
98 /^(y(es)?|no?|help|parrot( (bug|problem))?|bug|problem)$/i ||
99 length($subject) < 4 ||
110 #------------------------------------------------------------#
113 # Initialize the program.
115 # Get parrot information, process the options, create the message
116 # information (subject, to, body, etc.) depending on the type of report
117 # (ok, nok or bug report).
119 $is_linux = lc($^O
) eq 'linux';
120 $is_macos = $^O
eq 'MacOS';
121 $is_mswin32 = $^O
eq 'MSWin32';
122 $is_os2 = $^O
eq 'os2';
123 $is_vms = $^O
eq 'VMS';
126 ## Fetch Parrot information.
129 # Get parrot version.
130 # There will always be an up-to-date $parrot/VERSION
131 my $filename = File
::Spec
->catfile($parrotdir, "VERSION");
132 open(VERSION
, "<$filename") or die "Cannot open '$filename': $!";
133 $parrot{version
} = <VERSION
>;
134 chomp $parrot{version
};
135 close(VERSION
) or die "Cannot close '$filename': $!";
137 # Get parrot configuration, stored in $parrot/myconfig
138 $filename = File
::Spec
->catfile($parrotdir, "myconfig");
139 open(MYCONFIG
, "<$filename") or die "Cannot open '$filename': $!";
142 $parrot{myconfig
} = <MYCONFIG
>;
144 close(MYCONFIG
) or die "Cannot close '$filename': $!";
150 @ARGV = split m/\s+/,
151 MacPerl
::Ask
("Provide command-line args here (-h for help):")
152 if $is_macos && $MacPerl::Version
=~ /App/;
153 Getopt
::Long
::Configure
("no_bundling", "no_ignore_case", "auto_abbrev");
154 help
() unless GetOptions
156 "help|h", "version|V",
157 "send", "dump", "save",
158 "from|f=s", "to|test|t=s", "editor|e=s",
159 "subject|s=s", "category|C=s", "severity|S=s",
160 "input|input-file|i=s", "output|output-file|o=s",
161 "ok", "nok", "ack!", "quiet|q!" );
164 ## Report to be sent.
168 last ok_report
unless defined $opts{ok
};
170 # This is an ok report, woohoo!
171 $report{to
} = $std_to{ok
};
172 $report{subject
} = "OK: parrot $parrot{version} "
173 . "on $Config{archname} $Config{osvers}";
174 $report{body
} = "Parrot reported to build OK on this system.\n";
175 $report{category
} = "install";
176 $report{severity
} = "none";
181 # Ok reports do not need body, but nok and bug reports do need
183 if ( $opts{input
} ) {
184 # Report was pre-written, slurp it.
185 open BODY
, "<$opts{input}" or die "Can't open '$opts{input}': $!";
187 $report{body
} = <BODY
>;
188 close BODY
or die "Can't close '$opts{input}': $!";
190 # No file provided...
196 last nok_report
unless defined $opts{nok
};
198 # This a nok report, how sad... :-(
199 $report{to
} = $std_to{nok
};
200 $report{subject
} = "Not OK: parrot $parrot{version} "
201 . "on $Config{archname} $Config{osvers}";
202 $report{category
} = "install";
203 $report{severity
} = "none";
207 # Neither an ok nor a nok.
208 $report{to
} = $std_to{bug
};
209 $report{subject
} = $opts{subject
} || "";
210 $report{category
} = $opts{category
} || "";
211 $report{severity
} = $opts{severity
} || "";
214 # Test message, shortcuting recipent.
215 $report{to
} = $opts{to
} if $opts{to
};
222 $user = $is_mswin32 ?
$ENV{USERNAME
}
223 : $is_os2 ?
$ENV{USER
} || $ENV{LOGNAME
}
224 : $is_macos ?
$ENV{USER
}
225 : eval { getpwuid($<) }; # May be missing
227 # User address, used in message and in Reply-To header.
228 $report{from
} = $opts{from
} || "";
231 $editor = $ENV{VISUAL
} || $ENV{EDITOR
} || $ENV{EDIT
}
232 || ( $is_vms && "edit/tpu" )
233 || ( $is_mswin32 && "notepad" )
234 || ( $is_macos && "" )
243 eval "use Mail::Util;";
245 $domain = Mail
::Util
::maildomain
();
246 } elsif ($is_mswin32) {
247 $domain = $ENV{USERDOMAIN
};
249 require Sys
::Hostname
;
250 $domain = Sys
::Hostname
::hostname
();
252 $msgid = "<parrotbug_${VERSION}_${$}_".time."\@$domain>";
257 #------------------------------------------------------------#
260 # Query missing information in order to have a complete report.
261 sub query_missing_info
{
262 $report{subject
} = "" if trivial_subject
( $report{subject
} );
263 $report{subject
} = ask_for_subject
() unless $report{subject
};
264 $report{category
} = ask_for_alternative
( "category", \
@categories)
265 unless $report{category
};
266 $report{severity
} = ask_for_alternative
( "severity", \
@severities)
267 unless $report{severity
};
268 $report{from
} = ask_for_return_address
() unless $report{from
};
269 $report{body
} = ask_for_body
() unless $report{body
};
273 # Prompt for alternatives from a set of choices.
275 # The arguments are: the name of alternative, the choices (as an array
276 # ref), and the default answer. (first element if undef)
278 # Return the lowercased alternative chosen.
280 # Die if more than 5 wrong answers.
281 sub ask_for_alternative
{
282 my ( $what, $choices, $default ) = @_;
284 print <<EOT unless $opts{quiet};
285 Please pick a $what from the following:
290 $default ||= $choices->[0];
294 die "Invalid $alt: aborting.\n" if $err++ > 5;
295 print "Please enter a $what [$default]: ";
298 $alt = $default if $alt =~ /^\s*$/;
299 } until ( ($alt) = grep /^$alt/i, @
$choices );
306 # Prompt for a body, through an external editor.
308 unless ( $opts{quiet
} ) {
310 Now you need to supply the bug report. Try to make the report concise
311 but descriptive. Include any relevant detail. If you are reporting
312 something that does not work as you think it should, please try to
313 include example of both the actual result, and what you expected.
315 Some information about your local parrot configuration will
316 automatically be included at the end of the report. If you are using
317 any unusual version of parrot, please try and confirm exactly which
318 versions are relevant.
322 print "Press 'Enter' to continue...\n";
326 # Prompt for editor to use if none supplied.
327 if ( $opts{editor
} ) {
328 $editor = $opts{editor
};
331 ask_for_editor
($opts{quiet
} ?
"" : <<EOT);
332 You will probably want to use an editor to enter the report. If the
333 default editor proposed below is the editor you want to use, then just
334 press the 'Enter' key, otherwise type in the name of the editor you
340 $tmpfile = generate_filename
();
344 edit_bug_report
( $tmpfile );
346 open BODY
, "<$tmpfile" or die "Can't open '$tmpfile': $!";
351 close BODY
or die "Can't close '$tmpfile': $!";
353 print "\nYou provided an empty bug report!\n";
354 print "Press 'Enter' to continue...\n";
357 die "Aborting.\n" if $err++ == 5;
364 # Prompt for editor to use.
366 print shift() . "Editor [$editor]: ";
369 $editor = $entry if $entry ne "";
370 $opts{editor
} = $editor;
374 # Prompt for return address, return it.
375 sub ask_for_return_address
{
376 print <<EOT unless $opts{quiet};
377 Your e-mail address will be useful if you need to be contacted. If the
378 default shown below is not your full internet e-mail address, please
382 # Try and guess return address
385 require Mac
::InternetConfig
;
386 $guess = $Mac::InternetConfig
::InternetConfig
{
387 Mac
::InternetConfig
::kICEmail
()
390 $guess = $ENV{'REPLY-TO'} || $ENV{REPLYTO
} || "";
394 # Use $domain if we can.
396 $guess = $is_vms && !$Config{d_socket
} ?
397 "$domain\:\:$user" : "$user\@$domain";
402 print "Your address [$guess]: ";
405 $from = $guess if $from eq "";
411 # Prompt for subject of message.
413 # Return the subject chosen.
415 # Die if more than 5 wrong subjects.
416 sub ask_for_subject
{
417 print <<EOT unless $opts{quiet};
418 First of all, please provide a subject for the message. It should be a
419 concise description of the bug or problem. "parrot bug" or "parrot
420 problem" is not a concise description.
427 $err and print "\nThat doesn't look like a good subject. "
428 . "Please be more verbose.\n";
432 die "Aborting.\n" if $err++ == 5;
433 } while ( trivial_subject
($subject) );
439 # Launch an editor in which to edit the bug report.
440 sub edit_bug_report
{
441 my $filename = shift;
446 require ExtUtils
::MakeMaker
;
447 ExtUtils
::MM_MacOS
::launch_file
($filename);
448 print "Press Enter when done.\n";
451 $retval = system("$editor $filename");
454 # Check whether editor run was successful.
455 die <<EOT if $retval;
456 The editor you chose ('$editor') could apparently not be run! Did you
457 mistype the name of your editor?
465 #------------------------------------------------------------#
469 # Display everything collected.
471 print "==> Dumping message...\n";
472 print format_message
();
476 # Last chance to edit report.
478 # Prompt for editor to use if none supplied.
479 unless ( $opts{editor
} ) {
480 ask_for_editor
(<<EOT);
481 You will probably want to use an editor to modify the report. If the
482 default editor proposed below is the editor you want to use, then just
483 press the 'Enter' key, otherwise type in the name of the editor you
488 $tmpfile ||= $opts{input
};
492 edit_bug_report
( $tmpfile );
494 open BODY
, "<$tmpfile" or die "Can't open '$tmpfile': $!";
499 close BODY
or die "Can't close '$tmpfile': $!";
501 print "\nYou provided an empty bug report!\n";
502 print "Press 'Enter' to continue...\n";
505 die "Aborting.\n" if $err++ == 5;
508 $report{body
} = $body;
512 # Format the message with everything collected and return it.
516 # OS, arch, compiler...
519 osname= $Config{osname}
520 osvers= $Config{osvers}
521 arch= $Config{archname}
524 my $cc = $Config{cc
};
525 $report .= "cc= $cc $Config{${cc}.'version'}\n";
532 category=$report{category}
533 severity=$report{severity}
535 $report .= " ack=no\n" if ! $opts{ack
};
538 $report .= "---\n$report{body}\n";
541 $report .= "---\n$parrot{myconfig}\n---\n";
543 # ... and environment.
544 $report .= "Environment:\n";
545 my @env = qw
[ PATH LD_LIBRARY_PATH LANG SHELL HOME LOGDIR LANGUAGE
];
546 push @env, $Config{ldlibpthname
} if $Config{ldlibpthname
} ne '';
547 push @env, grep /^(?:PERL|LC_|LANG|CYGWIN)/, keys %ENV;
548 my %env; @env{@env} = @env;
549 for my $env (sort keys %env) {
551 exists $ENV{$env} ?
"=$ENV{$env}\n" : " (unset)\n";
558 # Print synopsis + help message and exit.
562 A program to help generate bug reports about parrot, and mail them.
563 It is designed to be used interactively. Normally no arguments will
566 Simplest usage: run '$0', and follow the prompts.
567 Usage: $0 [OPTIONS] [ACTIONS]
570 --ok Report successful build on this system to parrot
571 developers. Only use --ok if *everything* was ok:
572 if there were *any* problems at all, use --nok.
573 --nok Report unsuccessful build on this system.
574 --subject <subject> Subject to include with the message.
575 --category <category> Category of the bug report.
576 --severity <severity> Severity of the bug report.
577 --from <address> Your email address.
578 --editor <editor> Editor to use for editing the bug report.
579 --ack, --noack Don't send a bug received acknowledgement.
580 --input-file File containing the body of the report. Use this
581 to quickly send a prepared message.
582 --output-file File where parrotbug will save its bug report.
583 --to <address> Email address to send report to. (testing only)
585 Note: you will be prompted if the program miss some information.
591 --help Print this help message and exit.
592 --version Print version information and exit.
599 # Save message to file.
601 print "\n==> Saving message to file...\n";
602 if ( ! $opts{output
} ) {
603 print "Enter filename to save bug report: ";
604 $opts{output
} = <STDIN
>;
607 open OUTPUT
, ">$opts{output}" or die "Cannot open '$opts{output}': $!";
608 print OUTPUT format_message
();
609 close OUTPUT
or die "Cannot open '$opts{output}': $!";
611 print "Message saved.\n";
615 # Send message to final recipient.
617 print "==> Sending message to recipient...\n";
619 # On linux certain mail implementations won't accept the subject
620 # as "~s subject" and thus the Subject header will be corrupted
621 # so don't use Mail::Send to be safe
622 eval "require Mail::Send";
623 if ( $@
eq "" && !$is_linux) {
624 my $msg = new Mail
::Send Subject
=> $report{subject
}, To
=> $report{to
};
625 $msg->add( "Reply-To", $report{from
} );
628 print $fh format_message
();
631 print "\nMessage sent.\n";
635 for ( qw
[ /usr/lib
/sendmail /usr
/sbin/sendmail
636 /usr/ucblib
/sendmail /var
/qmail/bin
/sendmail
] ) {
637 $sendmail = $_, last if -e
$_;
640 die <<EOT if $sendmail eq "";
641 I am terribly sorry, but I cannot find sendmail, or a close
642 equivalent, and the perl package Mail::Send has not been installed, so
643 I can't send your bug report. We apologize for the inconvenience.
645 So you may attempt to find some way of sending your message, it has
646 been left in the file '$tmpfile'.
649 open(SENDMAIL
, "|$sendmail -t -oi") || die "'|$sendmail -t -oi' failed: $!";
651 print SENDMAIL
<<EOT;
653 Subject: $report{subject}
654 Reply-To: $report{from}
659 print SENDMAIL format_message
();
660 if (close(SENDMAIL
)) {
661 printf "\nMessage sent.\n";
663 warn "\nSendmail returned status '", $?
>> 8, "'\n";
669 # Print version information (of the parrotbug program) and exit.
673 This is $0, version $VERSION.
680 # Check whether actions have been provided on comand-line, otherwise
681 # prompt for what to do with bug report.
683 dump_report
() if $opts{dump};
684 save_report
() if $opts{save
};
685 send_report
() if $opts{send};
687 return if $opts{dump} || $opts{save
} || $opts{send};
689 # No actions provided on command-line, prompt for action.
693 print "Action (send,display,edit,save,quit): ";
696 dump_report
(), last sw
if /^d/i;
697 edit_report
(), last sw
if /^e/i;
698 save_report
(), last sw
if /^sa/i;
699 send_report
(), last sw
if /^se/i;
700 print "Uh?\n" unless /^q/i;
702 } until ( $action =~ /^q/i );
710 parrotbug - Parrot Bug Reporter
714 % ./parrotbug [options] [actions]
718 A program to help generate bug reports about parrot, and mail them.
719 It is designed to be used interactively. Normally no arguments will
723 =head1 COMMAND-LINE SWITCHES
728 Note: you will be prompted if the program miss some information.
734 Report unsuccessful build on this system to parrot developers.
738 Report successful build on this system to parrot developers Only use
739 C<--ok> if B<everything> was ok; if there were B<any> problems at all,
744 Subject of the report. You will be prompted if you don't supply one on
749 Category of the bug report. You will be prompted if you don't supply
750 one on the command-line.
754 Severity of the bug report. You will be prompted if you don't supply
755 one on the command-line.
759 Your email address. The program will try to guess one if you don't
760 provide one, but you'll still need to validate it.
764 Editor to use for editing the bug report.
766 =item B<--ack>, B<--noack>
768 Don't send a bug received acknowledgement.
770 =item B<--input-file>
772 File containing the body of the report. Use this to quickly send a
775 =item B<--output-file>
777 File where parrotbug will save its bug report, if you ask it to do so.
781 Email address to send report to. (for testing purposes only)
788 You can provide more than one action on the command-line. If none is
789 supplied, then you will be prompted for what to do.
795 Dump formatted report on standard output.
799 Save message to a file, in order for you to send it later from your
800 own. See C<--output> flag.
804 Try to send a mail with the report.
808 Print a short synopsis and exit.
812 Print version information and exit.
819 Jerome Quelin (E<lt>jquelin@cpan.orgE<gt>), with lots of good stuff taken from perlbug.
824 perlbug(1), parrot(1), diff(1), patch(1)