File Coverage

blib/lib/CGI/LogCarp.pm
Criterion Covered Total %
statement 201 284 70.7
branch 89 198 44.9
condition 16 42 38.1
subroutine 37 47 78.7
pod 33 36 91.6
total 376 607 61.9


line stmt bran cond sub pod time code
1             package CGI::LogCarp;
2              
3             # SCCS INFO: @(#) CGI::LogCarp.pm 4.48 20/06/06
4             # RCS INFO: $Id: CGI::LogCarp.pm,v 4.48 2020/06/06 mak Exp $
5             #
6             # Copyright (C) 1997,2020 Michael King (mikeking@cpan.org)
7             # Saint Louis, MO USA.
8             #
9             # This module is free software; you can redistribute it and/or
10             # modify it under the terms of the Artistic License 2.0.
11              
12             # SPDX-License-Identifier: Artistic-2.0-Perl
13              
14             =head1 NAME
15              
16             CGI::LogCarp - Error, log and debug streams, httpd style format
17              
18             CGI::LogCarp redefines the STDERR stream and allows the definition
19             of new STDBUG and STDLOG streams in such a way that all messages are
20             formatted similar to an HTTPD error log.
21              
22             Methods are defined for directing messages to STDERR, STDBUG, and STDLOG.
23             Each stream can be directed to its own location independent of the others.
24              
25             It can be used as a version-compatible drop-in replacement for the
26             CGI::Carp module. This means that version 4.48 of CGI::LogCarp provides
27             the same functionality, usage, and features as at least version 4.48
28             of CGI::Carp.
29              
30             =head1 SYNOPSIS
31              
32             use CGI::LogCarp qw( :STDBUG fatalsToBrowser );
33              
34             print "CGI::LogCarp version: ", CGI::LogCarp::VERSION;
35             DEBUGLEVEL 2;
36              
37             confess "It was my fault: $!";
38             cluck "What's going on here?";
39              
40             warn "This is most unusual.";
41             carp "It was your fault!";
42              
43             croak "We're outta here!";
44             die "I'm dying.\n";
45              
46             debug "Just for debugging: somevar=", $somevar, "\n";
47             logmsg "Just for logging: We're here.\n";
48             trace "detail=", $detail, "\n";
49              
50             carpout \*ERRFILE;
51             debugout \*DEBUGFILE;
52             logmsgout \*LOGFILE;
53              
54             is_STDOUT(\*ERRFILE)
55             is_STDERR(\*LOGFILE)
56             is_STDBUG(\*LOGFILE)
57             is_STDLOG(\*ERRFILE)
58              
59             =head1 DESCRIPTION
60              
61             CGI::LogCarp is a Perl package defining methods for directing
62             the existing STDERR stream as well as creating and directing
63             two new messaging streams, STDBUG and STDLOG.
64              
65             Their use was intended mainly for a CGI development environment,
66             or where separate facilities for errors, logging, and debugging
67             output are needed.
68              
69             This is because CGI scripts have a nasty habit of leaving warning messages
70             in the error logs that are neither time stamped nor fully identified.
71             Tracking down the script that caused the error is a pain. Differentiating
72             debug output or activity logging from actual error messages is a pain.
73             Logging application activity or producing debugging output are quite different
74             tasks than (ab)using the server's error log for this purpose.
75             This module fixes all of these problems.
76              
77             Replace the usual
78              
79             use Carp;
80              
81             or
82              
83             use CGI::Carp;
84              
85             with
86              
87             use CGI::LogCarp;
88              
89             And the standard C, C, C, C,
90             C, and C calls will automagically be replaced with methods
91             that write out nicely time-, process-, program-, and stream- stamped messages
92             to the STDERR, STDLOG, and STDBUG streams.
93              
94             The method to generate messages on the new STDLOG stream
95             is C. Calls to C will write out the same nicely
96             time-, process-, program-, and stream-stamped messages
97             described above to both the STDLOG and the STDBUG streams.
98              
99             The process number and the stream on which the message appeared
100             is embedded in the default message in order to disambiguate multiple
101             simultaneous executions as well as multiple streams directed
102             to the same location.
103              
104             Messages on multiple streams directed to the same location
105             do not receive multiple copies.
106              
107             Methods to generate messages on the new STDBUG stream
108             are C and C.
109              
110             =head2 Creating the New Streams
111              
112             In order to create the new streams, you must name them on the C line.
113             This is also referred to as importing a symbol. For example:
114              
115             use CGI::LogCarp qw( :STDERR :STDLOG :STDBUG );
116              
117             Note the :STDERR is not really necessary, as it is already defined in perl.
118             Importing the :STDERR symbol will not generate an error.
119              
120             By default, the STDLOG stream is duplicated from the STDERR stream,
121             and the STDBUG stream is duplicated from the STDOUT stream.
122              
123             =head2 Redirecting Error Messages
124              
125             By default, error messages are sent to STDERR. Most HTTPD servers
126             direct STDERR to the server's error log. Some applications may wish
127             to keep private error logs, distinct from the server's error log, or
128             they may wish to direct error messages to STDOUT so that the browser
129             will receive them (for debugging, not for public consumption).
130              
131             The C method is provided for this purpose.
132              
133             Because C is not exported by default,
134             you must import it explicitly by saying:
135              
136             use CGI::LogCarp qw( carpout );
137              
138             Note that for C, the STDERR stream is already defined,
139             so there is no need to explicitly create it by importing the STDERR symbol.
140             However,
141              
142             use CGI::LogCarp qw( :STDERR );
143              
144             will not generate an error, and will also import carpout for you.
145              
146             For CGI programs that need to send something to the HTTPD server's
147             real error log, the original STDERR stream has not been closed,
148             it has been saved as _STDERR. The reason for this is twofold.
149              
150             The first is that your CGI application might really need to write something
151             to the server's error log, unrelated to your own error log. To do so,
152             simply write directly to the _STDERR stream.
153              
154             The second is that some servers, when dealing with CGI scripts,
155             close their connection to the browser when the script closes
156             either STDOUT or STDERR. Some consider this a (mis)feature.
157              
158             Saving the program's initial STDERR in _STDERR is used
159             to prevent this from happening prematurely.
160              
161             Do not manipulate the _STDERR filehandle in any other way other than writing
162             to it.
163             For CGI applications, the C method formats and sends your message
164             to the HTTPD error log (on the _STDERR stream).
165              
166             =head2 Redirecting Log Messages
167              
168             A new stream, STDLOG, can be defined and used for log messages.
169             By default, STDLOG will be routed to STDERR. Most HTTPD servers
170             direct STDERR (and thus the default STDLOG also) to the server's error log.
171             Some applications may wish to keep private activity logs,
172             distinct from the server's error log, or they may wish to direct log messages
173             to STDOUT so that the browser will receive them (for debugging,
174             not for public consumption).
175              
176             The C method is provided for this purpose.
177              
178             Because C is not exported by default,
179             you must create the STDLOG stream and import them explicitly by saying:
180              
181             use CGI::LogCarp qw( :STDLOG );
182              
183             =head2 Redirecting Debug Messages
184              
185             A new stream, STDBUG, can be defined and used for debugging messages.
186             Since this stream is for producing debugging output,
187             the default STDBUG will be routed to STDOUT. Some applications may wish
188             to keep private debug logs, distinct from the application output, or
189             CGI applications may wish to leave debug messages directed to STDOUT
190             so that the browser will receive them (only when debugging).
191             Your program may also control the output by manipulating DEBUGLEVEL
192             in the application.
193              
194             The C method is provided for this purpose.
195              
196             Because the C method is not exported by default,
197             you must create the STDBUG stream and import them explicitly by saying:
198              
199             use CGI::LogCarp qw( :STDBUG );
200              
201             =head2 Redirecting Messages in General
202              
203             Each of these methods, C, C, and C,
204             requires one argument, which should be a reference to an open filehandle
205             for writing.
206             They should be called in a C block at the top of the application
207             so that compiler errors will be caught.
208              
209             This example creates and redirects the STDLOG stream,
210             as well as redirecting the STDERR stream to a browser,
211             formatting the error message as an HTML document:
212              
213             BEGIN {
214             use CGI::LogCarp qw( :STDLOG fatalsToBrowser );
215             # fatalsToBrowser doesn't stop messages going to STDERR,
216             # rather it replicates them on STDOUT. So we stop them here.
217             open(_STDERR,'>&STDERR'); close STDERR;
218             open(LOG,">>/var/logs/cgi-logs/mycgi-log")
219             or die "Unable to open mycgi-log: $!\n";
220             logmsgout \*LOG;
221             }
222              
223             NOTE: C, C, and C handle file locking
224             on systems that support flock so multiple simultaneous CGIs are not an issue.
225             However, flock might not operate as desired over network-mounted filesystems.
226              
227             If you want to send errors to the browser, give C a reference
228             to STDOUT:
229              
230             BEGIN {
231             use CGI::LogCarp qw( carpout );
232             carpout \*STDOUT;
233             }
234              
235             If you do this, be sure to send a Content-Type header immediately --
236             perhaps even within the BEGIN block -- to prevent server errors.
237             However, you probably want to take a look at importing the
238             C symbol and closing STDERR instead of doing this.
239             See the example above on how to do this.
240              
241             =head2 Passing filehandles
242              
243             You can pass filehandles to C, C, and C
244             in a variety of ways. The "correct" way according to Tom Christiansen
245             is to pass a reference to a filehandle GLOB (or if you are using the
246             FileHandle module, a reference to a anonymous filehandle GLOB):
247              
248             carpout \*LOG;
249              
250             This looks a little weird if you haven't mastered Perl's syntax,
251             so the following syntaxes are accepted as well:
252              
253             carpout(LOG) -or- carpout(\LOG)
254             carpout('LOG') -or- carpout(\'LOG')
255             carpout(main::LOG) -or- carpout(\main::LOG)
256             carpout('main::LOG') -or- carpout(\'main::LOG')
257             ... and so on
258              
259             FileHandle and other objects work as well.
260              
261             Using C, C, and C,
262             is not great for performance, so they are recommended for debugging purposes
263             or for moderate-use applications. You can also manipulate DEBUGLEVEL
264             to control the output during the execution of your program.
265              
266             =head2 Changing the Default Message Formats
267              
268             By default, the messages sent to the respective streams are formatted
269             as helpful time-, process-, program-, and stream-stamped messages.
270              
271             The process number (represented in the example output below as $$)
272             and the stream on which the message appears are displayed in the default
273             message format and serve to disambiguate multiple simultaneous executions
274             as well as multiple streams directed to the same location.
275              
276             For example:
277              
278             [Mon Sep 15 09:04:55 1997] $$ test.pl ERR: I'm confused at test.pl line 3.
279             [Mon Sep 15 09:04:55 1997] $$ test.pl BUG: answer=42.
280             [Mon Sep 15 09:04:55 1997] $$ test.pl LOG: I did something.
281             [Mon Sep 15 09:04:55 1997] $$ test.pl ERR: Got a warning: Permission denied.
282             [Mon Sep 15 09:04:55 1997] $$ test.pl ERR: I'm dying.
283              
284             You can, however, redefine your own message formats for each stream
285             if you don't like this one by using the C method.
286             This is not imported by default; you should import it on the use() line
287             like thus:
288              
289             use CGI::LogCarp qw( fatalsToBrowser set_message );
290             # fatalsToBrowser doesn't stop messages going to STDERR,
291             # rather it replicates them on STDOUT. So we stop them here.
292             open(_STDERR,'>&STDERR'); close STDERR;
293             set_message("It's not a bug, it's a feature!");
294              
295             use CGI::LogCarp qw( :STDLOG );
296             set_message(STDLOG, "Control: I'm here.");
297              
298             Note the varying syntax for C.
299              
300             The first parameter, if it is a filehandle, identifies the stream whose
301             message is being defined. Otherwise it specifies the message for the STDERR
302             stream. This non-filehandle first parameter form preserves compatibility with
303             CGI::Carp syntax.
304              
305             You may also pass in a code reference in order to create a custom
306             error message. At run time, your code will be called with the text
307             of the error message that caused the script
308              
309             BEGIN {
310             use CGI::LogCarp qw( fatalsToBrowser set_message );
311             # fatalsToBrowser doesn't stop messages going to STDERR,
312             # rather it replicates them on STDOUT. So we stop them here.
313             open(_STDERR,'>&STDERR'); close STDERR;
314             sub handle_errors {
315             my $msg = shift;
316             $msg =~ s/\&/&/gs;
317             $msg =~ s/
318             $msg =~ s/>/>/gs;
319             $msg =~ s/"/"/gs;
320             join("\n",
321             "

Aw shucks

",
322             "Got an error:",
323             "
", $msg, "
",
324             "");
325             }
326             set_message(\&handle_errors);
327             }
328              
329             In order to correctly intercept compile-time errors, you should
330             call C from within a C block.
331              
332             =head2 Making perl Errors Appear in the Browser Window
333              
334             If you want to send fatal (C or C) errors to the browser,
335             ask to import the special C symbol:
336              
337             BEGIN {
338             use CGI::LogCarp qw( fatalsToBrowser );
339             # fatalsToBrowser doesn't stop messages going to STDERR,
340             # rather it replicates them on STDOUT. So we stop them here.
341             open(_STDERR,'>&STDERR'); close STDERR;
342             }
343             die "Bad error here";
344              
345             Fatal errors will now be sent to the browser. Any messages sent to the
346             STDERR stream are now I reproduced on the STDOUT stream.
347             Using C also causes CGI::LogCarp to define a new message
348             format that arranges to send a minimal HTTP header and HTML document to the
349             browser so that even errors that occur early in the compile phase will be
350             shown. Any fatal (C) and nonfatal (C) messages are I produced
351             on the STDERR stream. They just also go to STDOUT.
352              
353             Certain web servers (Netscape) also send CGI STDERR output to the browser.
354             This causes a problem for CGI's because the STDERR stream is not buffered,
355             and thus if something gets sent to the STDERR stream before the normal
356             document header is produced, the browser will get very confused.
357              
358             The following line solves this problem. See above for examples with context.
359              
360             open(_STDERR,'>&STDERR'); close STDERR;
361              
362             =head2 Changing the fatalsToBrowser message format or document
363              
364             The default message generated by C is not the normal
365             C logging message, but instead displays the error message followed by
366             a short note to contact the Webmaster by e-mail with the time and date of the
367             error. You can use the C method to change it as described above.
368              
369             The default message generated on the STDLOG and STDBUG streams is formatted
370             differently, and is as described earlier.
371              
372             =head2 What are the Carp methods?
373              
374             The Carp methods that are replaced by CGI::LogCarp are useful in your
375             own modules, scripts, and CGI applications because they act like C
376             or C, but report where the error was in the code they were called from.
377             Thus, if you have a routine C that has a C in it,
378             then the C will report the error as occurring where C was
379             called, not where C was called.
380              
381             =head2 Forcing a Stack Trace
382              
383             As a debugging aid, you can force C to treat a C
384             as a C and a C as a C across I modules.
385             In other words, force a detailed stack trace to be given.
386             This can be very helpful when trying to understand why, or from where,
387             a warning or error is being generated.
388              
389             This feature is enabled by 'importing' the non-existant symbol
390             'verbose'. You would typically enable it on the command line by saying:
391              
392             perl -MCGI::LogCarp=verbose script.pl
393              
394             or by including the string C in the C
395             environment variable.
396              
397             You would typically enable it in a CGI application by saying:
398              
399             use CGI::LogCarp qw( verbose );
400              
401             Or, during your program's run by saying:
402              
403             CGI::LogCarp::import( 'verbose' );
404              
405             and calling C's import function directly.
406              
407             NOTE: This is a feature that is in Carp but apparently was not
408             implemented in CGI::Carp (as of v1.10).
409              
410             =head1 METHODS
411              
412             Unless otherwise stated all methods return either a true or false value,
413             with true meaning that the operation was a success.
414             When a method states that it returns a value,
415             failure will be returned as undef or an empty list.
416              
417             =head2 Streams and their methods
418              
419             The following methods are for generating a message on the respective stream:
420              
421             The STDERR stream: warn() and die()
422             The STDLOG stream: logmsg()
423             The STDBUG stream: debug() and trace()
424             The _STDERR stream: serverwarn()
425              
426             The following methods are for generating a message on the respective stream,
427             but will indicate the message location from the caller's perspective.
428             See the standard B module for details.
429              
430             The STDERR stream: carp(), croak(), cluck() and confess()
431              
432             The following methods are for manipulating the respective stream:
433              
434             The STDERR stream: carpout()
435             The STDLOG stream: logmsgout()
436             The STDBUG stream: debugout()
437              
438             The following methods are for manipulating the amount (or level)
439             of output filtering on the respective stream:
440              
441             The STDBUG stream: DEBUGLEVEL()
442             The STDLOG stream: LOGLEVEL()
443              
444             The following method defines the format of messages directed to a stream.
445             Often used by and/or in conjunction with C:
446              
447             set_message()
448              
449             =head2 Exported Package Methods
450              
451             By default, the only methods exported into your namespace are:
452              
453             warn, die, carp, croak, confess, and cluck
454              
455             When you import the :STDBUG tag, these additional symbols are exported:
456              
457             *STDBUG, debugmsgout, debug, trace, and DEBUGLEVEL
458              
459             When you import the :STDLOG tag, these additional symbols are exported:
460              
461             *STDLOG, logmsgout, logmsg and LOGLEVEL
462              
463             When you import the :STDERR tag, these additional symbols are exported:
464              
465             carpout
466              
467             These additional methods are not exported by default, and must be named:
468              
469             carpout, logmsgout, debugout, set_message
470              
471             The following are pseudo-symbols, in that they change the way CGI::LogCarp
472             works, but to not export any symbols in and of themselves.
473              
474             verbose, fatalsToBrowser
475              
476             =head2 Internal Package Methods
477              
478             The following methods are not exported but can be accessed directly
479             in the CGI::LogCarp package.
480              
481             The following methods are for comparing a filehandle to the respective stream:
482              
483             is_STDOUT()
484             is_STDERR()
485             is_STDBUG()
486             is_STDLOG()
487             is_realSTDERR()
488              
489             Each is explained in its own section below.
490              
491             =head2 Exported Package Variables
492              
493             No variables are exported into the caller's namespace.
494             However, the STDLOG and STDBUG streams are defined using typeglobs
495             in the C
namespace.
496              
497             =head2 Internal Package Variables
498              
499             =over
500              
501             =item $DEBUGLEVEL
502              
503             A number indicating the level of debugging output that is to occur.
504             At each increase in level, additional debugging output is allowed.
505              
506             Currently three levels are defined:
507              
508             0 - No messages are output on the STDBUG stream.
509             1 - debug() messages are output on the STDBUG stream.
510             2 - debug() and trace() messages are output on the STDBUG stream.
511              
512             It is recommended to use the DEBUGLEVEL method to get/set this value.
513              
514             =item $LOGLEVEL
515              
516             A number indicating the level of logging output that is to occur.
517             At each increase in level, additional logging output is allowed.
518              
519             Currently two levels are defined:
520              
521             0 - No messages are output on the STDLOG stream.
522             1 - logmsg() messages are output on the STDLOG stream.
523              
524             It is recommended to use the LOGLEVEL method to get/set this value.
525              
526             =back
527              
528             =head1 RETURN VALUE
529              
530             The value returned by executing the package is 1 (or true).
531              
532             =head1 ENVIRONMENT
533              
534             =head1 FILES
535              
536             =head1 ERRORS
537              
538             =head1 WARNINGS
539              
540             Operation on Win32 platforms has not been tested.
541              
542             CGI::Carp has some references to a C import symbol,
543             which appears to be an alternate name for C.
544             Internal comments refer to errorWrap. Since this is poorly
545             documented, I am speculating this is legacy and/or previous
546             implementation coding, and as such, have chosen not implement
547             the C symbol import in C. If some massively
548             popular module(s) I am currently unaware of is/are indeed using
549             this undocumented interface, please let me know.
550              
551             =head1 DIAGNOSTICS
552              
553             See importing the C pseudo-symbol in B.
554              
555             =head1 BUGS
556              
557             Check out what's left in the TODO file.
558              
559             =head1 RESTRICTIONS
560              
561             This module is free software; you can redistribute it and/or
562             modify it under the same terms as Perl itself.
563              
564             =head1 CPAN DEPENDENCIES
565              
566             =head1 LOCAL DEPENDENCIES
567              
568             =head1 SEE ALSO
569              
570             Carp, CGI::Carp
571              
572             =head1 NOTES
573              
574             carpout(), debugout(), and logmsgout() now perform file locking.
575              
576             I've attempted to track the features in C to the features in
577             the C module by Lincoln Stein. The version number of C
578             corresponds to the highest version of C module that this module
579             replicates all features and functionality. Thus version 1.10 of C
580             can be used as a drop-in replacement for versions 1.10 or lower of C.
581              
582             Due to the implementation of the Symbol.pm module, I have no choice but to
583             replace it with a version that supports extending the list of "global"
584             symbols. It is part of the CGI::LogCarp distribution.
585              
586             For speed reasons, the autoflush method is implemented here instead of
587             pulling in the entire FileHandle module.
588              
589             =head1 ACKNOWLEDGEMENTS
590              
591             Based heavily on the C module by Lincoln D. Stein ( lstein@genome.wi.mit.edu ).
592             Thanks to Andy Wardley ( abw@kfs.org ) for commenting the original C
593             module.
594              
595             Thanks to Michael G Schwern ( schwern@starmedia.net ) for the constructive input.
596              
597             =head1 AUTHORZ<>(S)
598              
599             mak - Michael King ( mikeking@cpan.org )
600              
601             =head1 HISTORY
602              
603             CGI::LogCarp.pm
604             v1.01 09/15/97 mak
605             v1.12 08/14/98 mak
606             v4.48 06/06/20 mak
607              
608             =head1 CHANGE LOG
609              
610             1.05 first posting to CPAN
611             1.12 major revision, tracking CGI::Carp
612             4.48 major revision to track current version of CGI::Carp.
613              
614             =head1 MODIFICATIONS
615              
616             =head1 COPYRIGHT
617              
618             Copyright (C) 1997,2020 Michael King ( mikeking@cpan.org )
619             Saint Louis, MO USA.
620              
621             This module is free software; you can redistribute it and/or
622             modify it under the terms of the Artistic License 2.0.
623              
624             This module is copyright (c) 1997,2020 by Michael King (mikeking@cpan.org)
625             and is made available to the Perl public under terms of the
626             Artistic License 2.0. See the file LICENSE for details
627             of copy and distribution terms.
628              
629             The authoritative text of the Artistic License 2.0 can be found here:
630             https://www.perlfoundation.org/artistic-license-20.html
631              
632             =head1 AVAILABILITY
633              
634             The latest version of this module is likely to be available from: CPAN.org
635              
636              
637             The best place to discuss this code is via email with the author.
638              
639             =cut
640              
641             # --- END OF PAGE --- #- - - - - - - - - - - - - - - - - - - - - - - - - - - -
642              
643             # Play nice
644             require 5.004;
645 6     6   4866 use strict;
  6         40  
  6         308  
646              
647             # The package name
648             package CGI::LogCarp;
649              
650             # Define external interface
651 6     6   46 use vars qw( @ISA @EXPORT @EXPORT_OK @EXPORT_FAIL %EXPORT_TAGS );
  6         11  
  6         365  
652 6     6   35 use Exporter;
  6         9  
  6         2720  
653              
654             # Inherit normal import/export mechanism from Exporter
655             @ISA = qw( Exporter );
656              
657             # Always exported into caller namespace
658             @EXPORT = qw( *STDERR confess croak carp cluck );
659              
660             # Externally visible if specified
661             @EXPORT_OK = qw(
662             logmsg trace debug
663             carpout logmsgout debugout
664             serverwarn
665             DEBUGLEVEL LOGLEVEL
666             is_STDOUT is_STDERR is_STDBUG is_STDLOG is_realSTDERR
667             set_message
668             *STDBUG *STDLOG
669             );
670              
671             # Export Tags
672             %EXPORT_TAGS = (
673             'STDBUG' => [ qw( *STDBUG debug trace debugout DEBUGLEVEL ), @EXPORT ],
674             'STDLOG' => [ qw( *STDLOG logmsg logmsgout LOGLEVEL ), @EXPORT ],
675             'STDERR' => [ qw( *STDERR carpout ), @EXPORT ],
676             );
677              
678             # Hook for psuedo-symbols (or modes)
679             @EXPORT_FAIL = qw( verbose *STDERR *STDLOG *STDBUG );
680             push @EXPORT_FAIL, qw( fatalsToBrowser ); # from CGI::Carp
681             push @EXPORT_OK, @EXPORT_FAIL;
682              
683             sub export_fail {
684             MODE: {
685 8     8 0 1983 shift;
  18         31  
686 18 100       48 last MODE unless scalar @_;
687 10 50       51 if ($_[0] eq 'verbose') {
    100          
    100          
    50          
    0          
688 0         0 Carp->import($_[0]); # Let Carp know what's going on
689 0         0 redo MODE;
690             } elsif ($_[0] eq '*STDLOG') { # Create the STDLOG stream
691 1 50       3 unless ($CGI::LogCarp::STDLOG) {
692 1 50       16 open(CGI::LogCarp::STDLOG,'>&STDERR')
693             or realdie("Could not create STDLOG stream: $!");
694 1         3 $CGI::LogCarp::STDLOG = $CGI::LogCarp::STDLOG = 1;
695             #Symbol::add_global('STDLOG');
696             }
697 1         2 redo MODE;
698             } elsif ($_[0] eq '*STDBUG') { # Create the STDBUG stream
699 1 50       3 unless ($CGI::LogCarp::STDBUG) {
700 1 50       17 open(CGI::LogCarp::STDBUG,'>&STDOUT')
701             or realdie("Could not create STDBUG stream: $!");
702 1         3 $CGI::LogCarp::STDBUG = $CGI::LogCarp::STDBUG = 1;
703             #Symbol::add_global('STDBUG');
704             }
705 1         2 redo MODE;
706             } elsif ($_[0] eq '*STDERR') { # Create the STDERR stream
707 8 100       37 unless (fileno(\*CGI::LogCarp::STDERR)) {
708 6 50       131 open(CGI::LogCarp::STDERR,'>&STDERR') or realdie();
709 6         19 $CGI::LogCarp::STDERR = $CGI::LogCarp::STDERR = 1;
710             }
711 8         19 redo MODE;
712             } elsif ($_[0] eq 'fatalsToBrowser') { # Turn it on
713 0         0 $CGI::LogCARP::fatalsToBrowser = 1;
714 0         0 redo MODE;
715             }
716             }
717 8         1620 return @_;
718             }
719              
720             # Standard packages
721 6     6   204 BEGIN { require Carp; } # We *DON'T* want to import Carp's symbols
722              
723             # CPAN packages
724              
725             # Local packages
726 6     6   2945 use Symbol; # 1.0201; # Make sure we are using the new one
  6         4997  
  6         452  
727 6     6   2851 use SelectSaver; # This must be *after* use Symbol 1.0201
  6         1674  
  6         446  
728              
729             # Package Version
730             $CGI::LogCarp::VERSION = "4.48";
731 0     0 0 0 sub VERSION () { $CGI::LogCarp::VERSION; };
732              
733             # Constants
734              
735             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
736              
737             # Compile-time initialization code
738             BEGIN {
739             # Save the real STDERR
740 6 50   6   25181 open(main::_STDERR,'>&STDERR') or realdie();
741             #Symbol::add_global("_STDERR");
742             # Alias STDERR to ours
743             #*STDERR = *main::STDERR;
744             }
745              
746             # Initialize the debug level (ON)
747             $CGI::LogCarp::DEBUGLEVEL = 1;
748              
749             # Initialize the log level (ON)
750             $CGI::LogCarp::LOGLEVEL = 1;
751              
752             # Initialize fatalsToBrowser flag (OFF)
753             $CGI::LogCARP::fatalsToBrowser = 0;
754             # Does Lincoln Stein use this elsewhere? What's wrap and errorWrap?
755              
756             # Initialize to default fatalsToBrowser message
757             $CGI::LogCarp::CUSTOM_STDERR_MSG = undef;
758             $CGI::LogCarp::CUSTOM_STDBUG_MSG = undef;
759             $CGI::LogCarp::CUSTOM_STDLOG_MSG = undef;
760              
761             # Grab Perl's signal handlers
762             # Note: Do we want to stack ours on top of whatever was there?
763             $main::SIG{'__WARN__'} = \&CGI::LogCarp::warn;
764             $main::SIG{'__DIE__'} = \&CGI::LogCarp::die;
765              
766             # Take over top-level definitions
767             # Not sure if we need this anymore with new Symbol.pm - mak
768             if ($CGI::LogCarp::STDLOG) {
769             *main::logmsg = *main::logmsg = \&CGI::LogCarp::logmsg;
770             }
771             if ($CGI::LogCarp::STDBUG) {
772             *main::debug = *main::debug = \&CGI::LogCarp::debug;
773             *main::trace = *main::trace = \&CGI::LogCarp::trace;
774             }
775              
776             # Predeclare and prototype our methods
777             sub stamp ($);
778             sub lock (*);
779             sub unlock (*);
780             sub streams_are_equal (**);
781             sub is_STDOUT (*);
782             sub is_STDERR (*);
783             sub is_STDLOG (*);
784             sub is_STDBUG (*);
785             sub is_realSTDERR (*);
786             sub realdie (@);
787             sub realwarn (@);
788             sub realbug (@);
789             sub reallog (@);
790             sub realserverwarn (@);
791             sub DEBUGLEVEL (;$);
792             sub LOGLEVEL (;$);
793             sub warn (@);
794             sub die (@);
795             sub logmsg (@);
796             sub debug (@);
797             sub trace (@);
798             sub serverwarn (@);
799             sub carp;
800             sub croak;
801             sub confess;
802             sub cluck;
803             sub carpout (;*);
804             sub logmsgout (;*);
805             sub debugout (;*);
806             sub autoflush (*);
807             sub to_filehandle;
808             sub set_message;
809              
810             # These are private aliases for various "levels"
811             # Alter these to your language/dialect if you'd like
812             my $NO = [ qw( no false off ) ];
813             my $YES = [ qw( yes true on ) ];
814             my $TRACE = [ qw( trace tracing ) ];
815              
816             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
817              
818             =head1 PACKAGE PUBLIC METHODS
819              
820             =head2 DEBUGLEVEL $LEVEL
821              
822             DEBUGLEVEL is a normal get/set method.
823              
824             When the scalar argument LEVEL is present, the DEBUGLEVEL will be set to LEVEL.
825             LEVEL is expected to be numeric, with the following case-insensitive
826             character-valued translations:
827              
828             NO, FALSE, and OFF all equate to a value of 0 (ZERO).
829             YES, TRUE, and ON all equate to a value of 1 (ONE).
830             TRACE or TRACING equate to a value of 2 (TWO).
831              
832             Values in scientific notation equate to their numeric equivalent.
833              
834             NOTE:
835              
836             All other character values of LEVEL equate to 0 (ZERO). This
837             will have the effect of turning off debug output.
838              
839             After this translation to a numeric value is performed,
840             the DEBUGLEVEL is set to LEVEL.
841              
842             Whenever the DEBUGLEVEL is set to a non-zero value (i.e. ON or TRACE),
843             the LOGLEVEL will be also set to 1 (ONE).
844              
845             The value of DEBUGLEVEL is then returned to the caller,
846             whether or not LEVEL is present.
847              
848             =cut
849              
850             sub DEBUGLEVEL (;$)
851             {
852 29     29 1 161 my ($value) = shift;
853 29 100       56 if (defined $value)
854             {
855             # Allow the usual non-numeric values
856 3 50       6 $value = 0 if scalar grep { m/^$value$/i } @$NO;
  9         66  
857 3 50       6 $value = 1 if scalar grep { m/^$value$/i } @$YES;
  9         40  
858 3 50       16 $value = 2 if scalar grep { m/^$value$/i } @$TRACE;
  6         34  
859              
860             # Coerce to numeric - note scientific notation is OK
861 3         8 $CGI::LogCarp::DEBUGLEVEL = 0 + $value;
862              
863             # Also turn on logging if we are debugging
864 3 50 66     19 LOGLEVEL(1) if ($CGI::LogCarp::DEBUGLEVEL
865             and not $CGI::LogCarp::LOGLEVEL);
866             }
867 29         98 $CGI::LogCarp::DEBUGLEVEL;
868             }
869              
870             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
871              
872             =head2 LOGLEVEL $LEVEL
873              
874             LOGLEVEL is a normal get/set method.
875              
876             When the scalar argument LEVEL is present, the LOGLEVEL will be set to LEVEL.
877             LEVEL is expected to be numeric, with the following case-insensitive
878             character-valued translations:
879              
880             NO, FALSE, and OFF all equate to a value of 0 (ZERO).
881             YES, TRUE, and ON all equate to a value of 1 (ONE).
882              
883             Values in scientific notation equate to their numeric equivalent.
884              
885             NOTE:
886              
887             All other character values of LEVEL equate to 0 (ZERO). This
888             will have the effect of turning off log output.
889              
890             After this translation to a numeric value is performed,
891             the LOGLEVEL is set to LEVEL.
892              
893             The value of LOGLEVEL is then returned to the caller,
894             whether or not LEVEL is present.
895              
896             =cut
897              
898             sub LOGLEVEL (;$)
899             {
900 17     17 1 158 my ($value) = shift;
901 17 100       35 if (defined $value)
902             {
903             # Allow the usual non-numeric values
904 3 50       6 $value = 0 if scalar grep { m/^$value$/i } @$NO;
  9         67  
905 3 50       5 $value = 1 if scalar grep { m/^$value$/i } @$YES;
  9         41  
906              
907             # Coerce to numeric - note scientific notation is OK
908 3         6 $CGI::LogCarp::LOGLEVEL = 0 + $value;
909             }
910 17         72 $CGI::LogCarp::LOGLEVEL;
911             }
912              
913             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
914              
915             =head2 warn @message
916              
917             This method is a replacement for Perl's builtin C.
918             The message is sent to the STDERR, STDLOG, and STDBUG streams.
919              
920             =cut
921              
922             sub warn (@)
923             {
924 15     15 1 171 my $message = join "", @_; # Flatten the list
925 15         46 my ($file,$line) = id(1);
926 15 50       95 $message .= " at $file line $line.\n" unless $message =~ /\n$/;
927 15         32 my $stamp = stamp "ERR";
928 15         76 $message =~ s/^/$stamp/gm;
929              
930 15 100       80 if ($CGI::LogCarp::STDBUG) {
931 3 50       8 realbug $message unless is_STDERR \*main::STDBUG;
932             }
933 15 100       56 if ($CGI::LogCarp::STDLOG) {
934 3 50 33     11 reallog $message unless (
935             is_STDERR(\*main::STDLOG)
936             or
937             is_STDBUG(\*main::STDLOG)
938             );
939             }
940 15         56 realwarn $message;
941             }
942              
943             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
944              
945             =head2 die @message
946              
947             This method is a replacement for Perl's builtin C.
948             The message is sent to the STDERR, STDLOG, and STDBUG streams.
949              
950             =cut
951              
952             sub die (@)
953             {
954 1     1 1 5 my $message = join "", @_; # Flatten the list
955 1         27 my $time = scalar localtime;
956 1         5 my ($file,$line) = id(1);
957 1 50       8 $message .= " at $file line $line.\n" unless $message =~ /\n$/;
958 1 50 33     3 fatalsToBrowser($message) if (
959             $CGI::LogCARP::fatalsToBrowser
960             and
961             CGI::LogCarp::_longmess() !~ /eval [{']/m
962             );
963 1         3 my $stamp = stamp "ERR";
964 1         5 $message =~ s/^/$stamp/gm;
965              
966 1 50       4 if ($CGI::LogCarp::STDBUG) {
967 0 0       0 realbug $message unless is_STDERR \*main::STDBUG;
968             }
969 1 50       3 if ($CGI::LogCarp::STDLOG) {
970 0 0 0     0 reallog $message unless (
971             is_STDERR(\*main::STDLOG)
972             or
973             is_STDBUG(\*main::STDLOG)
974             );
975             }
976 1         3 realdie $message;
977             }
978              
979             # The mod_perl package Apache::Registry loads CGI programs by calling eval.
980             # These evals don't count when looking at the stack backtrace.
981             # I've also allowed Netscape::Registry this functionality.
982             # You're welcome, Ben Sugars, nsapi_perl author. :)
983              
984             sub _longmess {
985 0     0   0 my $message = Carp::longmess();
986             my $mod_perl = (
987             $ENV{'GATEWAY_INTERFACE'}
988             and
989 0   0     0 $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-Perl\//
990             );
991 0 0       0 $message =~ s,eval[^\n]+(Apache|Netscape)/Registry\.pm.*,,s if $mod_perl;
992 0         0 return( $message );
993             }
994              
995             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
996              
997             # Take over carp(), croak(), confess(), and cluck();
998             # We never imported them from Carp, so we're ok
999              
1000             =head2 carp @message
1001              
1002             This method is a replacement for C.
1003             The message is sent to the STDERR, STDLOG, and STDBUG streams.
1004              
1005             # mak - this fixes a problem when you passed Carp::carp a list
1006             # like the documentation says ( shortmess uses $_[0] and not @_ ).
1007             # This has been fixed in later (post-1997) versions of Carp.pm.
1008             # Since Carp.pm has no version, I can't tell which one you have.
1009              
1010             =cut
1011              
1012             sub carp
1013             {
1014 1     1 1 315 CGI::LogCarp::warn( Carp::shortmess(join("",@_)) );
1015             }
1016              
1017             =head2 croak @message
1018              
1019             This method is a replacement for C.
1020             The message is sent to the STDERR, STDLOG, and STDBUG streams.
1021              
1022             # mak - this fixes a problem when you passed Carp::croak a list
1023             # like the documentation says ( shortmess uses $_[0] and not @_ ).
1024             # This has been fixed in later (post-1997) versions of Carp.pm.
1025             # Since Carp.pm has no version, I can't tell which one you have.
1026              
1027             =cut
1028              
1029             sub croak
1030             {
1031 1     1 1 217 CGI::LogCarp::die( Carp::shortmess(join("",@_)) );
1032             }
1033              
1034             =head2 confess @message
1035              
1036             This method is a replacement for C.
1037             The message is sent to the STDERR, STDLOG, and STDBUG streams.
1038              
1039             =cut
1040              
1041             sub confess
1042             {
1043 0     0 1 0 CGI::LogCarp::die( Carp::longmess(join("",@_)) );
1044             }
1045              
1046             =head2 cluck @message
1047              
1048             This method is a replacement for C.
1049             The message is sent to the STDERR, STDLOG, and STDBUG streams.
1050              
1051             =cut
1052              
1053             sub cluck
1054             {
1055 0     0 1 0 CGI::LogCarp::warn( Carp::longmess(join("",@_)) );
1056             }
1057              
1058             =head2 set_message $message
1059              
1060             =head2 set_message FILEHANDLE $message
1061              
1062             This method is a replacement for the CGI::Carp method of the same name.
1063             It defines the message format for the STDERR stream if FILEHANDLE is
1064             not specified. FILEHANDLE specifies which stream is having its message
1065             redefined. C<$message> is typically a reference to a subroutine.
1066              
1067             =cut
1068              
1069             sub set_message
1070             {
1071 0     0 1 0 my $message = shift;
1072             # CGI::Carp compatibility
1073 0 0       0 unless (scalar @_) {
1074 0         0 $CGI::LogCarp::CUSTOM_STDERR_MSG = $message;
1075 0         0 return $message;
1076             }
1077              
1078 0         0 my $fh = $message;
1079 0         0 $message = shift;
1080 0 0       0 if (is_STDERR $fh) {
    0          
    0          
1081 0         0 $CGI::LogCarp::CUSTOM_STDERR_MSG = $message;
1082             } elsif (is_STDLOG $fh) {
1083 0         0 $CGI::LogCarp::CUSTOM_STDLOG_MSG = $message;
1084             } elsif (is_STDBUG $fh) {
1085 0         0 $CGI::LogCarp::CUSTOM_STDBUG_MSG = $message;
1086             }
1087 0         0 return $message;
1088             }
1089              
1090             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1091              
1092             =head2 logmsg @message
1093              
1094             This method operates similarly to the C method.
1095             The message is sent to the STDLOG and STDBUG streams.
1096              
1097             =cut
1098              
1099             sub logmsg (@)
1100             {
1101 4     4 1 19 my $message = join "", @_; # Flatten the list
1102 4         10 my ($file,$line) = id(1);
1103 4 50       18 $message .= " at $file line $line.\n" unless $message =~ /\n$/;
1104 4         10 my $stamp = stamp "LOG";
1105 4         20 $message =~ s/^/$stamp/gm;
1106              
1107 4 50       11 if ($CGI::LogCarp::STDBUG) {
1108 0 0       0 realbug $message unless is_STDLOG \*main::STDBUG;
1109             }
1110 4         10 reallog $message;
1111             }
1112              
1113             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1114              
1115             =head2 debug @message
1116              
1117             This method operates similarly to the C method.
1118             The message is sent to the STDBUG stream when DEBUGLEVEL > 0.
1119              
1120             =cut
1121              
1122             sub debug (@)
1123             {
1124 4 100   4 1 8 return unless DEBUGLEVEL > 0;
1125 3         8 my $message = join "", @_; # Flatten the list
1126 3         7 my ($file,$line) = id(1);
1127 3 50       14 $message .= " at $file line $line.\n" unless $message =~ /\n$/;
1128 3         6 my $stamp = stamp "BUG";
1129 3         16 $message =~ s/^/$stamp/gm;
1130              
1131 3         8 realbug $message;
1132             }
1133              
1134             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1135              
1136             =head2 trace @message
1137              
1138             This method operates similarly to the C method.
1139             The message is sent to the STDBUG stream
1140             when DEBUGLEVEL is greater than one.
1141              
1142             =cut
1143              
1144             sub trace (@)
1145             {
1146 4 100   4 1 8 return unless DEBUGLEVEL > 1;
1147 1         3 my $message = join "", @_; # Flatten the list
1148 1         3 my ($file,$line) = id(1);
1149 1 50       6 $message .= " at $file line $line.\n" unless $message =~ /\n$/;
1150 1         3 my $stamp = stamp "TRC";
1151 1         5 $message =~ s/^/$stamp/gm;
1152              
1153 1         3 realbug $message;
1154             }
1155              
1156             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1157              
1158             =head2 serverwarn @message
1159              
1160             This method operates similarly to the C method.
1161             The message is sent to the STDBUG, STDLOG, STDERR and _STDERR streams.
1162             The _STDERR stream is typically is sent to a webserver's error log
1163             if used in a CGI program.
1164              
1165             =cut
1166              
1167             sub serverwarn (@)
1168             {
1169 0     0 1 0 my $message = join "", @_; # Flatten the list
1170 0         0 my ($file,$line) = id(1);
1171 0 0       0 $message .= " at $file line $line.\n" unless $message =~ /\n$/;
1172 0         0 my $stamp = stamp "SRV";
1173 0         0 $message =~ s/^/$stamp/gm;
1174              
1175 0 0       0 if ($CGI::LogCarp::STDBUG) {
1176 0 0 0     0 realbug $message unless (
1177             is_STDERR(\*main::STDBUG)
1178             or
1179             is_realSTDERR(\*main::STDBUG)
1180             );
1181             }
1182 0 0       0 if ($CGI::LogCarp::STDLOG) {
1183 0 0 0     0 reallog $message unless (
      0        
1184             is_STDERR(\*main::STDLOG)
1185             or
1186             is_STDBUG(\*main::STDLOG)
1187             or
1188             is_realSTDERR(\*main::STDLOG)
1189             );
1190             }
1191 0 0       0 realwarn $message unless is_realSTDERR \*STDERR;
1192 0         0 realserverwarn $message;
1193             }
1194              
1195             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1196              
1197             =head2 carpout FILEHANDLE
1198              
1199             A method to redirect the STDERR stream to the given FILEHANDLE.
1200             It accepts FILEHANDLE as a reference or a string.
1201              
1202             See the section on B
1203             and the section on B.
1204              
1205             =cut
1206              
1207             sub carpout (;*)
1208             {
1209 6   100 6 1 600 my ($fh) = shift || \*STDERR;
1210 6 50       27 $fh = to_filehandle($fh) or realdie "Invalid filehandle $fh\n";
1211 6 100       21 if (is_STDERR $fh) {
1212 1 50       25 open(STDERR,'>&main::_STDERR')
1213             or realdie "Unable to redirect STDERR: $!\n";
1214             } else {
1215 5 50       21 my $no = fileno($fh) or realdie "Invalid filehandle $fh\n";
1216 5 50       136 open(STDERR,'>&'.$no)
1217             or realdie "Unable to redirect STDERR: $!\n";
1218             }
1219 6         40 autoflush \*STDERR;
1220 6         58 \*STDERR;
1221             }
1222              
1223             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1224              
1225             =head2 logmsgout FILEHANDLE
1226              
1227             A method to redirect the STDLOG stream to the given FILEHANDLE.
1228             It accepts FILEHANDLE as a reference or a string.
1229              
1230             See the section on B
1231             and the section on B.
1232              
1233             =cut
1234              
1235             sub logmsgout (;*)
1236             {
1237 2   100 2 1 260 my ($fh) = shift || \*main::STDLOG;
1238 2 50       11 $fh = to_filehandle($fh) or realdie "Invalid filehandle $fh\n";
1239 2 100       7 if (is_STDLOG $fh) {
1240 1 50       32 open(main::STDLOG,'>&main::_STDERR')
1241             or realdie "Unable to redirect STDLOG: $!\n";
1242             } else {
1243 1 50       5 my $no = fileno($fh) or realdie "Invalid filehandle $fh\n";
1244 1 50       31 open(main::STDLOG,'>&'.$no)
1245             or realdie "Unable to redirect STDLOG: $!\n";
1246             }
1247 2         9 autoflush \*main::STDLOG;
1248 2         21 \*main::STDLOG;
1249             }
1250              
1251             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1252              
1253             =head2 debugout FILEHANDLE
1254              
1255             A method to redirect the STDBUG stream to the given FILEHANDLE.
1256             It accepts FILEHANDLE as a reference or a string.
1257              
1258             See the section on B
1259             and the section on B.
1260              
1261             =cut
1262              
1263             sub debugout (;*)
1264             {
1265 2   100 2 1 232 my ($fh) = shift || \*main::STDBUG;
1266 2 50       11 $fh = to_filehandle($fh) or realdie "Invalid filehandle $fh\n";
1267 2 100       4 if (is_STDBUG $fh) {
1268 1 50       31 open(main::STDBUG,'>&STDOUT')
1269             or realdie "Unable to redirect STDBUG: $!\n";
1270             } else {
1271 1 50       4 my $no = fileno($fh) or realdie "Invalid filehandle $fh\n";
1272 1 50       27 open(main::STDBUG,'>&'.$no)
1273             or realdie "Unable to redirect STDBUG: $!\n";
1274             }
1275 2         9 autoflush \*main::STDBUG;
1276 2         18 \*main::STDBUG;
1277             }
1278              
1279             sub fatalsToBrowser
1280             {
1281 0     0 1 0 my ($msg) = @_;
1282 0         0 $msg =~ s/&/&/gs;
1283 0         0 $msg =~ s/>/>/gs;
1284 0         0 $msg =~ s/
1285 0         0 $msg =~ s/\"/"/gs;
1286 0 0       0 my ($wm) = $ENV{'SERVER_ADMIN'} ?
1287             qq[the webmaster ($ENV{'SERVER_ADMIN'})] :
1288             "this site's webmaster";
1289 0         0 my ($outer_message) = <
1290             For help, please send mail to $wm, giving this error message
1291             and the time and date of the error.
1292             END
1293              
1294 0         0 print STDOUT "Content-type: text/html\013\010";
1295 0 0       0 if ($CGI::LogCarp::CUSTOM_STDERR_MSG) {
1296 0 0       0 if (ref($CGI::LogCarp::CUSTOM_STDERR_MSG) eq "CODE") {
1297 0         0 print STDOUT &{$CGI::LogCarp::CUSTOM_STDERR_MSG}($msg);
  0         0  
1298 0         0 return;
1299             } else {
1300 0         0 $outer_message = $CGI::LogCarp::CUSTOM_STDERR_MSG;
1301             }
1302             }
1303 0         0 print STDOUT <
1304            

Software Error:

1305            
$msg
1306            

1307             $outer_message
1308             END
1309              
1310             }
1311              
1312             # --- END OF PAGE --- #- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1313              
1314             =head2 to_filehandle EXPR
1315              
1316             Borrowed directly from CGI.pm by Lincoln Stein.
1317             It converts EXPR to a filehandle.
1318              
1319             =cut
1320              
1321             sub to_filehandle
1322             {
1323 120     120 1 168 my ($thingy) = shift;
1324 120 50       230 return undef unless $thingy;
1325 120 50       443 return $thingy if UNIVERSAL::isa($thingy,'GLOB');
1326 0 0       0 return $thingy if UNIVERSAL::isa($thingy,'FileHandle');
1327 0 0       0 if (!ref($thingy)) {
1328 0         0 my $caller = 1;
1329 0         0 while (my $package = caller($caller++)) {
1330 0 0       0 my ($tmp) = $thingy =~ m/[\':]/ ? $thingy : "$package\:\:$thingy";
1331 0 0       0 return $tmp if defined fileno($tmp);
1332             }
1333             }
1334 0         0 return undef;
1335             }
1336              
1337             =head2 is_STDOUT FILEHANDLE
1338              
1339             This method compares FILEHANDLE with the STDOUT stream
1340             and returns the boolean result.
1341              
1342             This method is not exported by default.
1343              
1344             =cut
1345              
1346             sub is_STDOUT (*)
1347             {
1348 0     0 1 0 my ($stream) = shift;
1349 0         0 streams_are_equal $stream, \*STDOUT;
1350             }
1351              
1352             =head2 is_STDERR FILEHANDLE
1353              
1354             This method compares FILEHANDLE with the STDERR stream
1355             and returns the boolean result.
1356              
1357             This method is not exported by default.
1358              
1359             =cut
1360              
1361             sub is_STDERR (*)
1362             {
1363 12     12 1 20 my ($stream) = shift;
1364 12         28 streams_are_equal $stream, \*STDERR;
1365             }
1366              
1367             =head2 is_STDBUG FILEHANDLE
1368              
1369             This method compares FILEHANDLE with the STDBUG stream
1370             and returns the boolean result.
1371              
1372             This method is not exported by default.
1373              
1374             =cut
1375              
1376             sub is_STDBUG (*)
1377             {
1378 5     5 1 12 my ($stream) = shift;
1379 5         12 streams_are_equal $stream, \*main::STDBUG;
1380             }
1381              
1382             =head2 is_STDLOG FILEHANDLE
1383              
1384             This method compares FILEHANDLE with the STDLOG stream
1385             and returns the boolean result.
1386              
1387             This method is not exported by default.
1388              
1389             =cut
1390              
1391             sub is_STDLOG (*)
1392             {
1393 2     2 1 4 my ($stream) = shift;
1394 2         5 streams_are_equal $stream, \*main::STDLOG;
1395             }
1396              
1397             =head2 is_realSTDERR FILEHANDLE
1398              
1399             This method compares FILEHANDLE with the _STDERR stream
1400             and returns the boolean result.
1401              
1402             This method is not exported by default.
1403              
1404             =cut
1405              
1406             sub is_realSTDERR (*)
1407             {
1408 0     0 1 0 my ($stream) = shift;
1409 0         0 streams_are_equal $stream, \*main::_STDERR;
1410             }
1411              
1412             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1413              
1414             =head1 PRIVATE METHODS
1415              
1416             =cut
1417              
1418             # Locks are fine grained
1419             # Do we need a higher level lock/unlock around a block of messages?
1420             # e.g.: lock \*STDLOG; iterated_log_writes @lines; unlock \*STDLOG;
1421              
1422             # These are the originals
1423              
1424             =head2 realwarn @MESSAGE
1425              
1426             This private method encapsulates Perl's underlying C method,
1427             actually producing the message on the STDERR stream.
1428             Locking is performed to ensure exclusive access while appending.
1429              
1430             This method is not exportable.
1431              
1432             =cut
1433              
1434             sub realwarn (@)
1435             {
1436 15     15 1 80 my $msg = join("",@_);
1437 15 50       34 if ($CGI::LogCarp::CUSTOM_STDERR_MSG) {
1438 0 0       0 if (ref($CGI::LogCarp::CUSTOM_STDERR_MSG) eq "CODE") {
1439 0         0 $msg = &{$CGI::LogCarp::CUSTOM_STDERR_MSG}($msg);
  0         0  
1440             }
1441             }
1442 15         63 lock \*STDERR;
1443 15         37 print { \*STDERR } $msg;
  15         1642  
1444 15         74 unlock \*STDERR;
1445             }
1446              
1447             =head2 realdie @MESSAGE
1448              
1449             This private method encapsulates Perl's underlying C method,
1450             actually producing the message on the STDERR stream and then terminating
1451             execution.
1452             Locking is performed to ensure exclusive access while appending.
1453              
1454             This method is not exportable.
1455              
1456             =cut
1457              
1458             sub realdie (@)
1459             {
1460 1     1 1 12 my $msg = join("",@_);
1461 1 50       3 if ($CGI::LogCarp::CUSTOM_STDERR_MSG) {
1462 0 0       0 if (ref($CGI::LogCarp::CUSTOM_STDERR_MSG) eq "CODE") {
1463 0         0 $msg = &{$CGI::LogCarp::CUSTOM_STDERR_MSG}($msg);
  0         0  
1464             }
1465             }
1466 1         4 lock \*STDERR;
1467 1         3 print { \*STDERR } $msg;
  1         15  
1468 1         5 unlock \*STDERR;
1469 1         11 CORE::die $msg; # This still goes to the original STDERR ... why?
1470             # my perl is 5.004_01 on BSD/OS 2.1 if that helps anyone
1471             }
1472              
1473             # The OS *should* unlock the stream as the process ends, but ...
1474 6     6   513 END { unlock \*STDERR; }
1475              
1476             =head2 reallog @MESSAGE
1477              
1478             This private method synthesizes an underlying C method,
1479             actually producing the message on the STDLOG stream.
1480             Locking is performed to ensure exclusive access while appending.
1481             The message will only be sent when LOGLEVEL is greater than zero.
1482              
1483             This method is not exportable.
1484              
1485             =cut
1486              
1487             sub reallog (@)
1488             {
1489 7 100   7 1 30 return unless LOGLEVEL > 0;
1490 5         14 my $msg = join("",@_);
1491 5 50       12 if ($CGI::LogCarp::CUSTOM_STDLOG_MSG) {
1492 0 0       0 if (ref($CGI::LogCarp::CUSTOM_STDLOG_MSG) eq "CODE") {
1493 0         0 $msg = &{$CGI::LogCarp::CUSTOM_STDLOG_MSG}($msg);
  0         0  
1494             }
1495             }
1496 5         14 lock \*main::STDLOG;
1497 5         11 print { \*main::STDLOG } $msg;
  5         109  
1498 5         21 unlock \*main::STDLOG;
1499             }
1500              
1501             =head2 realbug @message
1502              
1503             This private method synthesizes an underlying C method,
1504             actually producing the message on the STDBUG stream.
1505             Locking is performed to ensure exclusive access while appending.
1506             The message will only be sent when DEBUGLEVEL is greater than zero.
1507              
1508             This method is not exportable.
1509              
1510             =cut
1511              
1512             sub realbug (@)
1513             {
1514 7 100   7 1 13 return unless DEBUGLEVEL > 0;
1515 6         15 my $msg = join("",@_);
1516 6 50       13 if ($CGI::LogCarp::CUSTOM_STDBUG_MSG) {
1517 0 0       0 if (ref($CGI::LogCarp::CUSTOM_STDBUG_MSG) eq "CODE") {
1518 0         0 $msg = &{$CGI::LogCarp::CUSTOM_STDBUG_MSG}($msg);
  0         0  
1519             }
1520             }
1521 6         17 lock \*main::STDBUG;
1522 6         12 print { \*main::STDBUG } $msg;
  6         114  
1523 6         25 unlock \*main::STDBUG;
1524             }
1525              
1526             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1527              
1528             =head2 realserverwarn @message
1529              
1530             This private method synthesizes an underlying C method,
1531             actually producing the message on the _STDERR stream.
1532             Locking is performed to ensure exclusive access while appending.
1533             This stream is typically directed to the webserver's error log
1534             if used in a CGI program.
1535              
1536             This method is not exportable.
1537              
1538             =cut
1539              
1540             sub realserverwarn (@)
1541             {
1542 0     0 1 0 my $msg = join("",@_);
1543 0 0       0 if ($CGI::LogCarp::CUSTOM_STDERR_MSG) {
1544 0 0       0 if (ref($CGI::LogCarp::CUSTOM_STDERR_MSG) eq "CODE") {
1545 0         0 $msg = &{$CGI::LogCarp::CUSTOM_STDERR_MSG}($msg);
  0         0  
1546             }
1547             }
1548 0         0 lock \*main::_STDERR;
1549 0         0 print { \*main::_STDERR } $msg;
  0         0  
1550 0         0 unlock \*main::_STDERR;
1551             }
1552              
1553             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1554              
1555             =head2 id $level
1556              
1557             This private method returns the file, line, and basename
1558             of the currently executing function.
1559              
1560             This method is not exportable.
1561              
1562             =cut
1563              
1564             sub id ($)
1565             {
1566 24     24 1 42 my ($level) = shift;
1567 24         112 my ($pack, $file,$line, $sub) = caller $level;
1568 24         72 return ($file,$line);
1569             }
1570              
1571             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1572              
1573             =head2 stamp $stream_id
1574              
1575             A private method to construct a normalized timestamp prefix for a message.
1576              
1577             This method is not exportable.
1578              
1579             =cut
1580              
1581             sub stamp ($)
1582             {
1583 24     24 1 52 my ($stream_id) = shift;
1584 24         684 my $time = scalar localtime;
1585 24         126 my $process = sprintf("%6d",$$);
1586 24         74 my $frame = 0;
1587 24         41 my ($id,$pkg,$file);
1588 24         37 do {
1589 81         123 $id = $file;
1590 81         361 ($pkg,$file) = caller $frame++;
1591             } until !$file;
1592 24         164 ($id) = $id =~ m|([^/]+)$|;
1593 24         96 return "[$time] $process $id $stream_id: ";
1594             }
1595              
1596             # --- END OF PAGE --- #- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1597              
1598             =head2 streams_are_equal FILEHANDLE, FILEHANDLE
1599              
1600             This private method compares two FILEHANDLE streams to each other
1601             and returns the boolean result.
1602              
1603             This method is not exportable.
1604              
1605             Note: This function is probably not portable to non-Unix-based
1606             operating systems (i.e. NT, VMS, etc.).
1607              
1608             =cut
1609              
1610             sub streams_are_equal (**)
1611             {
1612 25     25 1 175 my ($fh1,$fh2) = @_;
1613 25 50       46 $fh1 = to_filehandle($fh1) or realdie "Invalid filehandle $fh1\n";
1614 25 50       44 $fh2 = to_filehandle($fh2) or realdie "Invalid filehandle $fh2\n";
1615 25         59 my $fno1 = fileno($fh1);
1616 25         50 my $fno2 = fileno($fh2);
1617 25 50 33     64 return 1 unless (defined $fno1 or defined $fno2); # true if both undef
1618 25 100 66     106 return unless (defined $fno1 and defined $fno2); # undef if one is undef
1619 22         258 my ($device1,$inode1) = stat $fh1;
1620 22         189 my ($device2,$inode2) = stat $fh2;
1621 22 100       186 ( $device1 == $device2 and $inode1 == $inode2 );
1622             }
1623              
1624             # --- END OF PAGE --- #- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1625              
1626             # Some flock-related globals for lock/unlock
1627 6     6   57 use Fcntl qw( /^LOCK_/ );
  6         11  
  6         1546  
1628 6     6   3400 use POSIX qw( /^SEEK_/ );
  6         49146  
  6         32  
1629              
1630             =head2 lock FILEHANDLE
1631              
1632             A private method that uses Perl's builtin C and C
1633             to obtain an exclusive lock on the stream specified by FILEHANDLE.
1634             A lock is only attempted on actual files that are writeable.
1635              
1636             This method is not exportable.
1637              
1638             =cut
1639              
1640             sub lock (*)
1641             {
1642 27     27 1 58 my ($fh) = shift;
1643 27 50       50 $fh = to_filehandle($fh) or realdie "Invalid filehandle $fh\n";
1644 27 50       76 my $no = fileno($fh) or return;
1645 27 50 33     466 return unless ( -f $fh and -w _ );
1646 27         234 flock $fh, LOCK_EX;
1647             # Just in case someone appended while we weren't looking...
1648 27         256 seek $fh, 0, SEEK_END;
1649             }
1650              
1651             =head2 unlock FILEHANDLE
1652              
1653             A private method that uses Perl's builtin C
1654             to release any exclusive lock on the stream specified by FILEHANDLE.
1655             An unlock is only attempted on actual files that are writeable.
1656              
1657             This method is not exportable.
1658              
1659             =cut
1660              
1661             sub unlock (*)
1662             {
1663 33     33 1 83 my ($fh) = shift;
1664 33 50       65 $fh = to_filehandle($fh) or realdie "Invalid filehandle $fh\n";
1665 33 50       85 my $no = fileno($fh) or return;
1666 33 100 66     506 return unless ( -f $fh and -w _ );
1667 31         343 flock $fh, LOCK_UN;
1668             }
1669              
1670             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1671              
1672             # Right out of IO::Handle 5.005_01
1673              
1674             # This is the only method we need from FileHandle
1675             sub autoflush (*)
1676             {
1677 10 50   10 0 69 my $old = SelectSaver->new(qualify($_[0],caller)) if ref($_[0]);
1678 10         289 my $prev = $|;
1679 10 50       39 $| = @_ > 1 ? $_[1] : 1;
1680 10         38 $prev;
1681             }
1682              
1683             # --- END OF PAGE ---^L#- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1684             # End of CGI::LogCarp.pm
1685             # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1686             1;