This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 5.003_01: utils/perlbug.PL
[perl5.git] / utils / perlbug.PL
... / ...
CommitLineData
1#!/usr/local/bin/perl
2
3use Config;
4use File::Basename qw(&basename &dirname);
5
6# List explicitly here the variables you want Configure to
7# generate. Metaconfig only looks for shell variables, so you
8# have to mention them as if they were shell variables, not
9# %Config entries. Thus you write
10# $startperl
11# to ensure Configure will look for $Config{startperl}.
12
13# This forces PL files to create target in same directory as PL file.
14# This is so that make depend always knows where to find PL derivatives.
15chdir(dirname($0));
16($file = basename($0)) =~ s/\.PL$//;
17$file =~ s/\.pl$//
18 if ($^O eq 'VMS' or $^O eq 'os2'); # "case-forgiving"
19
20open OUT,">$file" or die "Can't create $file: $!";
21
22print "Extracting $file (with variable substitutions)\n";
23
24# In this section, perl variables will be expanded during extraction.
25# You can use $Config{...} to use Configure variables.
26
27print OUT <<"!GROK!THIS!";
28$Config{'startperl'}
29 eval 'exec perl -S \$0 "\$@"'
30 if 0;
31!GROK!THIS!
32
33# In the following, perl variables are not expanded during extraction.
34
35print OUT <<'!NO!SUBS!';
36
37use Config;
38use Getopt::Std;
39
40BEGIN {
41 eval "use Mail::Send;";
42 $::HaveSend = ($@ eq "");
43 eval "use Mail::Util;";
44 $::HaveUtil = ($@ eq "");
45};
46
47
48use strict;
49
50sub paraprint;
51
52
53my($Version) = "1.14";
54
55# Changed in 1.06 to skip Mail::Send and Mail::Util if not available.
56# Changed in 1.07 to see more sendmail execs, and added pipe output.
57# Changed in 1.08 to use correct address for sendmail.
58# Changed in 1.09 to close the REP file before calling it up in the editor.
59# Also removed some old comments duplicated elsewhere.
60# Changed in 1.10 to run under VMS without Mail::Send; also fixed
61# temp filename generation.
62# Changed in 1.11 to clean up some text and removed Mail::Send deactivator.
63# Changed in 1.12 to check for editor errors, make save/send distinction
64# clearer and add $ENV{REPLYTO}.
65# Changed in 1.13 to hopefully make it more difficult to accidentally
66# send mail
67# Changed in 1.14 to make the prompts a little more clear on providing
68# helpful information. Also let file read fail gracefully.
69
70# TODO: Allow the user to re-name the file on mail failure, and
71# make sure failure (transmission-wise) of Mail::Send is
72# accounted for.
73
74my( $file, $usefile, $cc, $address, $perlbug, $testaddress, $filename,
75 $subject, $from, $verbose, $ed,
76 $fh, $me, $Is_VMS, $msg, $body, $andcc );
77
78Init();
79
80if($::opt_h) { Help(); exit; }
81
82if(!-t STDIN) {
83 paraprint <<EOF;
84Please use perlbug interactively. If you want to
85include a file, you can use the -f switch.
86EOF
87 die "\n";
88}
89
90if($::opt_d or !-t STDOUT) { Dump(*STDOUT); exit; }
91
92Query();
93Edit() unless $usefile;
94NowWhat();
95Send();
96
97exit;
98
99sub Init {
100
101 # -------- Setup --------
102
103 $Is_VMS = $^O eq 'VMS';
104
105 getopts("dhva:s:b:f:r:e:SCc:t");
106
107
108 # This comment is needed to notify metaconfig that we are
109 # using the $perladmin, $cf_by, and $cf_time definitions.
110
111
112 # -------- Configuration ---------
113
114 # perlbug address
115 $perlbug = 'perlbug@perl.com';
116
117 # Test address
118 $testaddress = 'perlbug-test@perl.com';
119
120 # Target address
121 $address = $::opt_a || ($::opt_t ? $testaddress : $perlbug);
122
123 # Possible administrator addresses, in order of confidence
124 # (Note that cf_email is not mentioned to metaconfig, since
125 # we don't really want it. We'll just take it if we have to.)
126 $cc = ($::opt_C ? "" : (
127 $::opt_c || $::Config{perladmin} || $::Config{cf_email} || $::Config{cf_by}
128 ));
129
130 # Users address, used in message and in Reply-To header
131 $from = $::opt_r || "";
132
133 # Include verbose configuration information
134 $verbose = $::opt_v || 0;
135
136 # Subject of bug-report message
137 $subject = $::opt_s || "";
138
139 # Send a file
140 $usefile = ($::opt_f || 0);
141
142 # File to send as report
143 $file = $::opt_f || "";
144
145 # Body of report
146 $body = $::opt_b || "";
147
148 # Editor
149 $ed = ( $::opt_e || $ENV{VISUAL} || $ENV{EDITOR} || $ENV{EDIT} ||
150 ($Is_VMS ? "edit/tpu" : "vi")
151 );
152
153
154 # My username
155 $me = getpwuid($<);
156
157}
158
159
160sub Query {
161
162 # Explain what perlbug is
163
164 paraprint <<EOF;
165This program provides an easy way to create a message reporting a bug in
166perl, and e-mail it to $address.
167
168EOF
169
170
171 # Prompt for subject of message, if needed
172 if(! $subject) {
173 paraprint <<EOF;
174First of all, please provide a subject for the
175message. It should be a concise description of
176the bug or problem.
177
178EOF
179 print "Subject: ";
180
181 $subject = <>;
182 chop $subject;
183
184 my($err)=0;
185 while( $subject =~ /^\s*$/ ) {
186 print "\nPlease enter a subject: ";
187 $subject = <>;
188 chop $subject;
189 if($err++>5) {
190 die "Aborting.\n";
191 }
192 }
193 }
194
195
196 # Prompt for return address, if needed
197 if( !$from) {
198
199 # Try and guess return address
200 my($domain);
201
202 if($::HaveUtil) {
203 $domain = Mail::Util::maildomain();
204 } elsif ($Is_VMS) {
205 require Sys::Hostname;
206 $domain = Sys::Hostname::hostname();
207 } else {
208 $domain = `hostname`.".".`domainname`;
209 $domain =~ s/[\r\n]+//g;
210 }
211
212 my($guess);
213
214 if( !$domain) {
215 $guess = "";
216 } elsif ($Is_VMS && !$::Config{'has_sockets'}) {
217 $guess = "$domain\:\:$me";
218 } else {
219 $guess = "$me\@$domain" if $domain;
220 $guess = "$me\@unknown.addresss" unless $domain;
221 }
222
223 $guess = $ENV{'REPLYTO'} if defined($ENV{'REPLYTO'});
224 $guess = $ENV{"REPLY-TO"} if defined($ENV{'REPLY-TO'});
225
226 if( $guess ) {
227 paraprint <<EOF;
228
229
230Your e-mail address will be useful if you need to be contacted. If the
231default shown is not your full internet e-mail address, please correct it.
232
233EOF
234 } else {
235 paraprint <<EOF;
236
237So that you may be contacted if necessary, please enter
238your full internet e-mail address here.
239
240EOF
241 }
242 print "Your address [$guess]: ";
243
244 $from = <>;
245 chop $from;
246
247 if($from eq "") { $from = $guess }
248
249 }
250
251 #if( $from =~ /^(.*)\@(.*)$/ ) {
252 # $mailname = $1;
253 # $maildomain = $2;
254 #}
255
256 if( $from eq $cc or $me eq $cc ) {
257 # Try not to copy ourselves
258 $cc = "yourself";
259 }
260
261
262 # Prompt for administrator address, unless an override was given
263 if( !$::opt_C and !$::opt_c ) {
264 paraprint <<EOF;
265
266
267A copy of this report can be sent to your local
268perl administrator. If the address is wrong, please
269correct it, or enter 'none' or 'yourself' to not send
270a copy.
271
272EOF
273
274 print "Local perl administrator [$cc]: ";
275
276 my($entry) = scalar(<>);
277 chop $entry;
278
279 if($entry ne "") {
280 $cc = $entry;
281 if($me eq $cc) { $cc = "" }
282 }
283
284 }
285
286 if($cc =~ /^(none|yourself|me|myself|ourselves)$/i) { $cc = "" }
287
288 $andcc = " and $cc" if $cc;
289
290editor:
291
292 # Prompt for editor, if no override is given
293 if(! $::opt_e and ! $::opt_f and ! $::opt_b) {
294 paraprint <<EOF;
295
296
297Now you need to supply the bug report. Try to make
298the report concise but descriptive. Include any
299relevant detail. If you are reporting something
300that does not work as you think it should, please
301try to include example of both the actual
302result, and what you expected.
303
304Some information about your local
305perl configuration will automatically be included
306at the end of the report. If you are using any
307unusual version of perl, please try and confirm
308exactly which versions are relevant.
309
310You will probably want to use an editor to enter
311the report. If "$ed" is the editor you want
312to use, then just press Enter, otherwise type in
313the name of the editor you would like to use.
314
315If you would like to use a prepared file, type
316"file", and you will be asked for the filename.
317
318EOF
319
320 print "Editor [$ed]: ";
321
322 my($entry) =scalar(<>);
323 chop $entry;
324
325 $usefile = 0;
326 if($entry eq "file") {
327 $usefile = 1;
328 } elsif($entry ne "") {
329 $ed = $entry;
330 }
331 }
332
333
334 # Generate scratch file to edit report in
335
336 {
337 my($dir) = $Is_VMS ? 'sys$scratch:' : '/tmp/';
338 $filename = "bugrep0$$";
339 $filename++ while -e "$dir$filename";
340 $filename = "$dir$filename";
341 }
342
343
344 # Prompt for file to read report from, if needed
345
346 if( $usefile and ! $file) {
347filename:
348 paraprint <<EOF;
349
350What is the name of the file that contains your report?
351
352EOF
353
354 print "Filename: ";
355
356 my($entry) = scalar(<>);
357 chop($entry);
358
359 if($entry eq "") {
360 paraprint <<EOF;
361
362No filename? I'll let you go back and choose an editor again.
363
364EOF
365 goto editor;
366 }
367
368 if(!-f $entry or !-r $entry) {
369 paraprint <<EOF;
370
371I'm sorry, but I can't read from `$entry'. Maybe you mistyped the name of
372the file? If you don't want to send a file, just enter a blank line and you
373can get back to the editor selection.
374
375EOF
376 goto filename;
377 }
378 $file = $entry;
379
380 }
381
382
383 # Generate report
384
385 open(REP,">$filename");
386
387 print REP <<EOF;
388This is a bug report for perl from $from,
389generated with the help of perlbug $Version running under perl $].
390
391EOF
392
393 if($body) {
394 print REP $body;
395 } elsif($usefile) {
396 open(F,"<$file") or die "Unable to read report file from `$file': $!\n";
397 while(<F>) {
398 print REP $_
399 }
400 close(F);
401 } else {
402 print REP "[Please enter your report here]\n";
403 }
404
405 Dump(*REP);
406 close(REP);
407
408}
409
410sub Dump {
411 local(*OUT) = @_;
412
413 print OUT <<EOF;
414
415
416
417Site configuration information for perl $]:
418
419EOF
420
421 if( $::Config{cf_by} and $::Config{cf_time}) {
422 print OUT "Configured by $::Config{cf_by} at $::Config{cf_time}.\n\n";
423 }
424
425 print OUT Config::myconfig;
426
427 if($verbose) {
428 print OUT "\nComplete configuration data for perl $]:\n\n";
429 my($value);
430 foreach (sort keys %::Config) {
431 $value = $::Config{$_};
432 $value =~ s/'/\\'/g;
433 print OUT "$_='$value'\n";
434 }
435 }
436}
437
438sub Edit {
439 # Edit the report
440
441 if($usefile) {
442 $usefile = 0;
443 paraprint <<EOF;
444
445Please make sure that the name of the editor you want to use is correct.
446
447EOF
448 print "Editor [$ed]: ";
449
450 my($entry) =scalar(<>);
451 chop $entry;
452
453 if($entry ne "") {
454 $ed = $entry;
455 }
456 }
457
458tryagain:
459 if(!$usefile and !$body) {
460 my($sts) = system("$ed $filename");
461 if( $Is_VMS ? !($sts & 1) : $sts ) {
462 #print "\nUnable to run editor!\n";
463 paraprint <<EOF;
464
465The editor you chose (`$ed') could apparently not be run!
466Did you mistype the name of your editor? If so, please
467correct it here, otherwise just press Enter.
468
469EOF
470 print "Editor [$ed]: ";
471
472 my($entry) =scalar(<>);
473 chop $entry;
474
475 if($entry ne "") {
476 $ed = $entry;
477 goto tryagain;
478 } else {
479
480 paraprint <<EOF;
481
482You may want to save your report to a file, so you can edit and mail it
483yourself.
484EOF
485 }
486 }
487 }
488}
489
490sub NowWhat {
491
492 # Report is done, prompt for further action
493 if( !$::opt_S ) {
494 while(1) {
495
496 paraprint <<EOF;
497
498
499Now that you have completed your report, would you like to send
500the message to $address$andcc, display the message on
501the screen, re-edit it, or cancel without sending anything?
502You may also save the message as a file to mail at another time.
503
504EOF
505
506 print "Action (Send/Display/Edit/Cancel/Save to File): ";
507 my($action) = scalar(<>);
508 chop $action;
509
510 if( $action =~ /^(f|sa)/i ) { # <F>ile/<Sa>ve
511 print "\n\nName of file to save message in [perlbug.rep]: ";
512 my($file) = scalar(<>);
513 chop $file;
514 if($file eq "") { $file = "perlbug.rep" }
515
516 open(FILE,">$file");
517 open(REP,"<$filename");
518 print FILE "To: $address\nSubject: $subject\n";
519 print FILE "Cc: $cc\n" if $cc;
520 print FILE "Reply-To: $from\n" if $from;
521 print FILE "\n";
522 while(<REP>) { print FILE }
523 close(REP);
524 close(FILE);
525
526 print "\nMessage saved in `$file'.\n";
527 exit;
528
529 } elsif( $action =~ /^(d|l|sh)/i ) { # <D>isplay, <L>ist, <Sh>ow
530 # Display the message
531 open(REP,"<$filename");
532 while(<REP>) { print $_ }
533 close(REP);
534 } elsif( $action =~ /^se/i ) { # <S>end
535 # Send the message
536 print "\
537Are you certain you want to send this message?
538Please type \"yes\" if you are: ";
539 my($reply) = scalar(<STDIN>);
540 chop($reply);
541 if( $reply eq "yes" ) {
542 last;
543 } else {
544 paraprint <<EOF;
545
546That wasn't a clear "yes", so I won't send your message. If you are sure
547your message should be sent, type in "yes" (without the quotes) at the
548confirmation prompt.
549
550EOF
551
552 }
553 } elsif( $action =~ /^[er]/i ) { # <E>dit, <R>e-edit
554 # edit the message
555 Edit();
556 #system("$ed $filename");
557 } elsif( $action =~ /^[qc]/i ) { # <C>ancel, <Q>uit
558 1 while unlink($filename); # remove all versions under VMS
559 print "\nCancelling.\n";
560 exit(0);
561 } elsif( $action =~ /^s/ ) {
562 paraprint <<EOF;
563
564I'm sorry, but I didn't understand that. Please type "send" or "save".
565EOF
566 }
567
568 }
569 }
570}
571
572
573sub Send {
574
575 # Message has been accepted for transmission -- Send the message
576
577 if($::HaveSend) {
578
579 $msg = new Mail::Send Subject => $subject, To => $address;
580
581 $msg->cc($cc) if $cc;
582 $msg->add("Reply-To",$from) if $from;
583
584 $fh = $msg->open;
585
586 open(REP,"<$filename");
587 while(<REP>) { print $fh $_ }
588 close(REP);
589
590 $fh->close;
591
592 } else {
593 if ($Is_VMS) {
594 if ( ($address =~ /@/ and $address !~ /^\w+%"/) or
595 ($cc =~ /@/ and $cc !~ /^\w+%"/) ){
596 my($prefix);
597 foreach (qw[ IN MX SMTP UCX PONY WINS ],'') {
598 $prefix = "$_%",last if $ENV{"MAIL\$PROTOCOL_$_"};
599 }
600 $address = qq[${prefix}"$address"] unless $address =~ /^\w+%"/;
601 $cc = qq[${prefix}"$cc"] unless !$cc || $cc =~ /^\w+%"/;
602 }
603 $subject =~ s/"/""/g; $address =~ s/"/""/g; $cc =~ s/"/""/g;
604 my($sts) = system(qq[mail/Subject="$subject" $filename. "$address","$cc"]);
605 if (!($sts & 1)) { die "Can't spawn off mail\n\t(leaving bug report in $filename): $sts\n;" }
606 } else {
607 my($sendmail) = "";
608
609 foreach (qw(/usr/lib/sendmail /usr/sbin/sendmail /usr/ucblib/sendmail))
610 {
611 $sendmail = $_, last if -e $_;
612 }
613
614 paraprint <<"EOF" and die "\n" if $sendmail eq "";
615
616I am terribly sorry, but I cannot find sendmail, or a close equivalent, and
617the perl package Mail::Send has not been installed, so I can't send your bug
618report. We apologize for the inconveniencence.
619
620So you may attempt to find some way of sending your message, it has
621been left in the file `$filename'.
622
623EOF
624
625 open(SENDMAIL,"|$sendmail -t");
626 print SENDMAIL "To: $address\n";
627 print SENDMAIL "Subject: $subject\n";
628 print SENDMAIL "Cc: $cc\n" if $cc;
629 print SENDMAIL "Reply-To: $from\n" if $from;
630 print SENDMAIL "\n\n";
631 open(REP,"<$filename");
632 while(<REP>) { print SENDMAIL $_ }
633 close(REP);
634
635 close(SENDMAIL);
636 }
637
638 }
639
640 print "\nMessage sent.\n";
641
642 1 while unlink($filename); # remove all versions under VMS
643
644}
645
646sub Help {
647 print <<EOF;
648
649A program to help generate bug reports about perl5, and mail them.
650It is designed to be used interactively. Normally no arguments will
651be needed.
652
653Usage:
654$0 [-v] [-a address] [-s subject] [-b body | -f file ]
655 [-r returnaddress] [-e editor] [-c adminaddress | -C] [-S] [-t]
656
657Simplest usage: run "$0", and follow the prompts.
658
659Options:
660
661 -v Include Verbose configuration data in the report
662 -f File containing the body of the report. Use this to
663 quickly send a prepared message.
664 -S Send without asking for confirmation.
665 -a Address to send the report to. Defaults to `$address'.
666 -c Address to send copy of report to. Defaults to `$cc'.
667 -C Don't send copy to administrator.
668 -s Subject to include with the message. You will be prompted
669 if you don't supply one on the command line.
670 -b Body of the report. If not included on the command line, or
671 in a file with -f, you will get a chance to edit the message.
672 -r Your return address. The program will ask you to confirm
673 this if you don't give it here.
674 -e Editor to use.
675 -t Test mode. The target address defaults to `$testaddress'.
676 -d Data mode (the default if you redirect or pipe output.)
677 This prints out your configuration data, without mailing
678 anything. You can use this with -v to get more complete data.
679
680EOF
681}
682
683sub paraprint {
684 my @paragraphs = split /\n{2,}/, "@_";
685 print "\n\n";
686 for (@paragraphs) { # implicit local $_
687 s/(\S)\s*\n/$1 /g;
688 write;
689 print "\n";
690 }
691
692}
693
694
695format STDOUT =
696^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
697$_
698.
699!NO!SUBS!
700
701close OUT or die "Can't close $file: $!";
702chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
703exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';