File Coverage

blib/lib/CGI/LogCarp.pm
Criterion Covered Total %
statement 203 284 71.4
branch 94 198 47.4
condition 18 42 42.8
subroutine 37 47 78.7
pod 33 36 91.6
total 385 607 63.4


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

Aw shucks

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

Software Error:

1299            
$msg
1300            

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