3 # Copyright (C) 2004-2007, The Perl Foundation.
7 eval 'exec perl -w -S $0 ${1+"$@"}'
8 if $running_under_some_shell;
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_mswin32 = $^O
eq 'MSWin32';
121 $is_os2 = $^O
eq 'os2';
122 $is_vms = $^O
eq 'VMS';
125 ## Fetch Parrot information.
128 # Get parrot version.
129 # There will always be an up-to-date $parrot/VERSION
130 my $filename = File
::Spec
->catfile($parrotdir, "VERSION");
131 open(VERSION
, "<$filename") or die "Cannot open '$filename': $!";
132 $parrot{version
} = <VERSION
>;
133 chomp $parrot{version
};
134 close(VERSION
) or die "Cannot close '$filename': $!";
136 # Get parrot configuration, stored in $parrot/myconfig
137 $filename = File
::Spec
->catfile($parrotdir, "myconfig");
138 open(MYCONFIG
, "<$filename") or die "Cannot open '$filename': $!";
141 $parrot{myconfig
} = <MYCONFIG
>;
143 close(MYCONFIG
) or die "Cannot close '$filename': $!";
149 Getopt
::Long
::Configure
("no_bundling", "no_ignore_case", "auto_abbrev");
150 help
() unless GetOptions
152 "help|h", "version|V",
153 "send", "dump", "save",
154 "from|f=s", "to|test|t=s", "editor|e=s",
155 "subject|s=s", "category|C=s", "severity|S=s",
156 "input|input-file|i=s", "output|output-file|o=s",
157 "ok", "nok", "ack!", "quiet|q!" );
160 ## Report to be sent.
164 last ok_report
unless defined $opts{ok
};
166 # This is an ok report, woohoo!
167 $report{to
} = $std_to{ok
};
168 $report{subject
} = "OK: parrot $parrot{version} "
169 . "on $Config{archname} $Config{osvers}";
170 $report{body
} = "Parrot reported to build OK on this system.\n";
171 $report{category
} = "install";
172 $report{severity
} = "none";
177 # Ok reports do not need body, but nok and bug reports do need
179 if ( $opts{input
} ) {
180 # Report was pre-written, slurp it.
181 open BODY
, "<$opts{input}" or die "Can't open '$opts{input}': $!";
183 $report{body
} = <BODY
>;
184 close BODY
or die "Can't close '$opts{input}': $!";
186 # No file provided...
192 last nok_report
unless defined $opts{nok
};
194 # This a nok report, how sad... :-(
195 $report{to
} = $std_to{nok
};
196 $report{subject
} = "Not OK: parrot $parrot{version} "
197 . "on $Config{archname} $Config{osvers}";
198 $report{category
} = "install";
199 $report{severity
} = "none";
203 # Neither an ok nor a nok.
204 $report{to
} = $std_to{bug
};
205 $report{subject
} = $opts{subject
} || "";
206 $report{category
} = $opts{category
} || "";
207 $report{severity
} = $opts{severity
} || "";
210 # Test message, shortcuting recipent.
211 $report{to
} = $opts{to
} if $opts{to
};
218 $user = $is_mswin32 ?
$ENV{USERNAME
}
219 : $is_os2 ?
$ENV{USER
} || $ENV{LOGNAME
}
220 : $is_macos ?
$ENV{USER
}
221 : eval { getpwuid($<) }; # May be missing
223 # User address, used in message and in Reply-To header.
224 $report{from
} = $opts{from
} || "";
227 $editor = $ENV{VISUAL
} || $ENV{EDITOR
} || $ENV{EDIT
}
228 || ( $is_vms && "edit/tpu" )
229 || ( $is_mswin32 && "notepad" )
230 || ( $is_macos && "" )
239 eval "use Mail::Util;";
241 $domain = Mail
::Util
::maildomain
();
242 } elsif ($is_mswin32) {
243 $domain = $ENV{USERDOMAIN
};
245 require Sys
::Hostname
;
246 $domain = Sys
::Hostname
::hostname
();
248 $msgid = "<parrotbug_${VERSION}_${$}_".time."\@$domain>";
253 #------------------------------------------------------------#
256 # Query missing information in order to have a complete report.
257 sub query_missing_info
{
258 $report{subject
} = "" if trivial_subject
( $report{subject
} );
259 $report{subject
} = ask_for_subject
() unless $report{subject
};
260 $report{category
} = ask_for_alternative
( "category", \
@categories)
261 unless $report{category
};
262 $report{severity
} = ask_for_alternative
( "severity", \
@severities)
263 unless $report{severity
};
264 $report{from
} = ask_for_return_address
() unless $report{from
};
265 $report{body
} = ask_for_body
() unless $report{body
};
269 # Prompt for alternatives from a set of choices.
271 # The arguments are: the name of alternative, the choices (as an array
272 # ref), and the default answer. (first element if undef)
274 # Return the lowercased alternative chosen.
276 # Die if more than 5 wrong answers.
277 sub ask_for_alternative
{
278 my ( $what, $choices, $default ) = @_;
280 print <<EOT unless $opts{quiet};
281 Please pick a $what from the following:
286 $default ||= $choices->[0];
290 die "Invalid $alt: aborting.\n" if $err++ > 5;
291 print "Please enter a $what [$default]: ";
294 $alt = $default if $alt =~ /^\s*$/;
295 } until ( ($alt) = grep /^$alt/i, @
$choices );
302 # Prompt for a body, through an external editor.
304 unless ( $opts{quiet
} ) {
306 Now you need to supply the bug report. Try to make the report concise
307 but descriptive. Include any relevant detail. If you are reporting
308 something that does not work as you think it should, please try to
309 include example of both the actual result, and what you expected.
311 Some information about your local parrot configuration will
312 automatically be included at the end of the report. If you are using
313 any unusual version of parrot, please try and confirm exactly which
314 versions are relevant.
318 print "Press 'Enter' to continue...\n";
322 # Prompt for editor to use if none supplied.
323 if ( $opts{editor
} ) {
324 $editor = $opts{editor
};
327 ask_for_editor
($opts{quiet
} ?
"" : <<EOT);
328 You will probably want to use an editor to enter the report. If the
329 default editor proposed below is the editor you want to use, then just
330 press the 'Enter' key, otherwise type in the name of the editor you
336 $tmpfile = generate_filename
();
340 edit_bug_report
( $tmpfile );
342 open BODY
, "<$tmpfile" or die "Can't open '$tmpfile': $!";
347 close BODY
or die "Can't close '$tmpfile': $!";
349 print "\nYou provided an empty bug report!\n";
350 print "Press 'Enter' to continue...\n";
353 die "Aborting.\n" if $err++ == 5;
360 # Prompt for editor to use.
362 print shift() . "Editor [$editor]: ";
365 $editor = $entry if $entry ne "";
366 $opts{editor
} = $editor;
370 # Prompt for return address, return it.
371 sub ask_for_return_address
{
372 print <<EOT unless $opts{quiet};
373 Your e-mail address will be useful if you need to be contacted. If the
374 default shown below is not your full internet e-mail address, please
378 # Try and guess return address
380 $guess = $ENV{'REPLY-TO'} || $ENV{REPLYTO
} || "";
383 # Use $domain if we can.
385 $guess = $is_vms && !$Config{d_socket
} ?
386 "$domain\:\:$user" : "$user\@$domain";
391 print "Your address [$guess]: ";
394 $from = $guess if $from eq "";
400 # Prompt for subject of message.
402 # Return the subject chosen.
404 # Die if more than 5 wrong subjects.
405 sub ask_for_subject
{
406 print <<EOT unless $opts{quiet};
407 First of all, please provide a subject for the message. It should be a
408 concise description of the bug or problem. "parrot bug" or "parrot
409 problem" is not a concise description.
416 $err and print "\nThat doesn't look like a good subject. "
417 . "Please be more verbose.\n";
420 $subject = q{} unless defined $subject;
422 die "Aborting.\n" if $err++ == 5;
423 } while ( trivial_subject
($subject) );
429 # Launch an editor in which to edit the bug report.
430 sub edit_bug_report
{
431 my $filename = shift;
435 $retval = system("$editor $filename");
437 # Check whether editor run was successful.
438 die <<EOT if $retval;
439 The editor you chose ('$editor') could apparently not be run! Did you
440 mistype the name of your editor?
448 #------------------------------------------------------------#
452 # Display everything collected.
454 print "==> Dumping message...\n";
455 print format_message
();
459 # Last chance to edit report.
461 # Prompt for editor to use if none supplied.
462 unless ( $opts{editor
} ) {
463 ask_for_editor
(<<EOT);
464 You will probably want to use an editor to modify the report. If the
465 default editor proposed below is the editor you want to use, then just
466 press the 'Enter' key, otherwise type in the name of the editor you
471 $tmpfile ||= $opts{input
};
475 edit_bug_report
( $tmpfile );
477 open BODY
, "<$tmpfile" or die "Can't open '$tmpfile': $!";
482 close BODY
or die "Can't close '$tmpfile': $!";
484 print "\nYou provided an empty bug report!\n";
485 print "Press 'Enter' to continue...\n";
488 die "Aborting.\n" if $err++ == 5;
491 $report{body
} = $body;
495 # Format the message with everything collected and return it.
499 # OS, arch, compiler...
502 osname= $Config{osname}
503 osvers= $Config{osvers}
504 arch= $Config{archname}
507 my $cc = $Config{cc
};
508 #$report .= "cc= $cc $Config{${cc}.'version'}\n";
509 $report .= "cc= $cc\n";
516 category=$report{category}
517 severity=$report{severity}
519 $report .= " ack=no\n" if ! $opts{ack
};
522 $report .= "---\n$report{body}\n";
525 $report .= "---\n$parrot{myconfig}\n---\n";
527 # ... and environment.
528 $report .= "Environment:\n";
529 my @env = qw
[ PATH LD_LIBRARY_PATH LANG SHELL HOME LOGDIR LANGUAGE
];
530 push @env, $Config{ldlibpthname
} if $Config{ldlibpthname
} ne '';
531 push @env, grep /^(?:PERL|LC_|LANG|CYGWIN)/, keys %ENV;
534 for my $env (sort keys %env) {
535 my $env_value = exists $ENV{$env} ?
"=$ENV{$env}\n" : " (unset)\n";
536 $report .= " $env $env_value";
543 # Print synopsis + help message and exit.
547 A program to help generate bug reports about parrot, and mail them.
548 It is designed to be used interactively. Normally no arguments will
551 Simplest usage: run '$0', and follow the prompts.
552 Usage: $0 [OPTIONS] [ACTIONS]
555 --ok Report successful build on this system to parrot
556 developers. Only use --ok if *everything* was ok:
557 if there were *any* problems at all, use --nok.
558 --nok Report unsuccessful build on this system.
559 --subject <subject> Subject to include with the message.
560 --category <category> Category of the bug report.
561 --severity <severity> Severity of the bug report.
562 --from <address> Your email address.
563 --editor <editor> Editor to use for editing the bug report.
564 --ack, --noack Don't send a bug received acknowledgement.
565 --input-file File containing the body of the report. Use this
566 to quickly send a prepared message.
567 --output-file File where parrotbug will save its bug report.
568 --to <address> Email address to send report to. (testing only)
570 Note: you will be prompted if the program miss some information.
576 --help Print this help message and exit.
577 --version Print version information and exit.
584 # Save message to file.
586 print "\n==> Saving message to file...\n";
587 if ( ! $opts{output
} ) {
588 print "Enter filename to save bug report: ";
589 $opts{output
} = <STDIN
>;
592 open OUTPUT
, ">$opts{output}" or die "Cannot open '$opts{output}': $!";
593 print OUTPUT format_message
();
594 close OUTPUT
or die "Cannot open '$opts{output}': $!";
596 print "Message saved.\n";
600 # Send message to final recipient.
602 print "==> Sending message to recipient...\n";
604 # On linux certain mail implementations won't accept the subject
605 # as "~s subject" and thus the Subject header will be corrupted
606 # so don't use Mail::Send to be safe
607 eval "require Mail::Send";
608 if ( $@
eq "" && !$is_linux) {
609 my $msg = new Mail
::Send Subject
=> $report{subject
}, To
=> $report{to
};
610 $msg->add( "Reply-To", $report{from
} );
613 print $fh format_message
();
616 print "\nMessage sent.\n";
620 for ( qw
[ /usr/lib
/sendmail /usr
/sbin/sendmail
621 /usr/ucblib
/sendmail /var
/qmail/bin
/sendmail
] ) {
622 $sendmail = $_, last if -e
$_;
625 die <<EOT if $sendmail eq "";
626 I am terribly sorry, but I cannot find sendmail, or a close
627 equivalent, and the perl package Mail::Send has not been installed, so
628 I can't send your bug report. We apologize for the inconvenience.
630 So you may attempt to find some way of sending your message, it has
631 been left in the file '$tmpfile'.
634 open(SENDMAIL
, "|$sendmail -t -oi") || die "'|$sendmail -t -oi' failed: $!";
636 print SENDMAIL
<<EOT;
638 Subject: $report{subject}
639 Reply-To: $report{from}
644 print SENDMAIL format_message
();
645 if (close(SENDMAIL
)) {
646 printf "\nMessage sent.\n";
648 warn "\nSendmail returned status '", $?
>> 8, "'\n";
654 # Print version information (of the parrotbug program) and exit.
658 This is $0, version $VERSION.
665 # Check whether actions have been provided on comand-line, otherwise
666 # prompt for what to do with bug report.
668 dump_report
() if $opts{dump};
669 save_report
() if $opts{save
};
670 send_report
() if $opts{send};
672 return if $opts{dump} || $opts{save
} || $opts{send};
674 # No actions provided on command-line, prompt for action.
678 print "Action (send,display,edit,save,quit): ";
681 dump_report
(), last sw
if /^d/i;
682 edit_report
(), last sw
if /^e/i;
683 save_report
(), last sw
if /^sa/i;
684 send_report
(), last sw
if /^se/i;
685 print "Uh?\n" unless /^q/i;
687 } until ( $action =~ /^q/i );
695 parrotbug - Parrot Bug Reporter
699 % ./parrotbug [options] [actions]
703 A program to help generate bug reports about parrot, and mail them.
704 It is designed to be used interactively. Normally no arguments will
708 =head1 COMMAND-LINE SWITCHES
713 Note: you will be prompted if the program miss some information.
719 Report unsuccessful build on this system to parrot developers.
723 Report successful build on this system to parrot developers Only use
724 C<--ok> if B<everything> was ok; if there were B<any> problems at all,
729 Subject of the report. You will be prompted if you don't supply one on
734 Category of the bug report. You will be prompted if you don't supply
735 one on the command-line.
739 Severity of the bug report. You will be prompted if you don't supply
740 one on the command-line.
744 Your email address. The program will try to guess one if you don't
745 provide one, but you'll still need to validate it.
749 Editor to use for editing the bug report.
751 =item B<--ack>, B<--noack>
753 Don't send a bug received acknowledgement.
755 =item B<--input-file>
757 File containing the body of the report. Use this to quickly send a
760 =item B<--output-file>
762 File where parrotbug will save its bug report, if you ask it to do so.
766 Email address to send report to. (for testing purposes only)
773 You can provide more than one action on the command-line. If none is
774 supplied, then you will be prompted for what to do.
780 Dump formatted report on standard output.
784 Save message to a file, in order for you to send it later from your
785 own. See C<--output> flag.
789 Try to send a mail with the report.
793 Print a short synopsis and exit.
797 Print version information and exit.
804 Jerome Quelin (E<lt>jquelin@cpan.orgE<gt>), with lots of good stuff taken from perlbug.
809 perlbug(1), parrot(1), diff(1), patch(1)
815 # cperl-indent-level: 4
818 # vim: expandtab shiftwidth=4: