File Coverage

blib/lib/TIGR/Foundation.pm
Criterion Covered Total %
statement 28 570 4.9
branch 0 206 0.0
condition 0 192 0.0
subroutine 10 62 16.1
pod 40 50 80.0
total 78 1080 7.2


line stmt bran cond sub pod time code
1             # $Id: Foundation.pm,v 1.1 2004/04/28 15:03:43 aphillip Exp $
2              
3             package TIGR::Foundation;
4             {
5              
6             =head1 NAME
7              
8             TIGR::Foundation - TIGR Foundation object
9              
10             =head1 SYNOPSIS
11              
12             use TIGR::Foundation;
13             my $obj_instance = new TIGR::Foundation;
14              
15             =head1 DESCRIPTION
16              
17             This module defines a structure for Perl programs to utilize
18             logging, version reporting, and dependency checking in a simple way.
19              
20             =cut
21              
22             BEGIN {
23 1     1   1286 require 5.006_00; # error if using Perl < v5.6.0
24             }
25              
26 1     1   5 use strict;
  1         2  
  1         20  
27 1     1   4 use Cwd;
  1         2  
  1         51  
28 1     1   4 use Cwd 'chdir';
  1         2  
  1         41  
29 1     1   6 use Cwd 'abs_path';
  1         2  
  1         51  
30 1     1   8 use File::Basename;
  1         3  
  1         82  
31 1     1   606 use Getopt::Long;
  1         10784  
  1         6  
32 1     1   511 use IO::Handle;
  1         4705  
  1         51  
33 1     1   354 use POSIX qw(strftime);
  1         5248  
  1         9  
34 1     1   1782 use Sys::Hostname;
  1         1248  
  1         5396  
35              
36             require Exporter;
37              
38             our @ISA;
39             our @EXPORT;
40             @ISA = ('Exporter');
41             @EXPORT = qw(
42             isReadableFile
43             isWritableFile
44             isExecutableFile
45             isCreatableFile
46             isReadableDir
47             isWritableDir
48             isCreatableDir
49             isCreatablePath
50              
51             getISODate
52             getSybaseDate
53             getMySQLDate
54             getFilelabelDate
55             getLogfileDate
56             );
57              
58             ## internal variables and identifiers
59             our $REVISION = (qw$Revision: 1.1 $)[-1];
60             our $VERSION = '1.41';
61             our $VERSION_STRING = "$VERSION (Build $REVISION)";
62             our @DEPEND = (); # there are no dependencies
63              
64              
65             ## prototypes
66              
67             # Functional Class : general
68             sub new();
69             sub getProgramInfo($);
70             sub runCommand($);
71              
72             # Functional Class : depend
73             sub printDependInfo();
74             sub printDependInfoAndExit();
75             sub addDependInfo(@);
76              
77             # Functional Class : version
78             sub getVersionInfo();
79             sub printVersionInfo();
80             sub printVersionInfoAndExit();
81             sub setVersionInfo($);
82             sub setVersionHandler($);
83              
84             # Functional Class : help
85             sub printHelpInfo();
86             sub printHelpInfoAndExit();
87             sub setHelpInfo($);
88              
89             # Functional Class : usage
90             sub printUsageInfo();
91             sub printUsageInfoAndExit();
92             sub setUsageInfo($);
93              
94             # Functional Class : files
95             sub isReadableFile($);
96             sub isExecutableFile($);
97             sub isWritableFile($);
98             sub isCreatableFile($);
99             sub isReadableDir($);
100             sub isWritableDir($);
101             sub isCreatableDir($);
102             sub isCreatablePath($);
103              
104             # Functional Class : date
105             sub getISODate(;@);
106             sub getSybaseDate(;@);
107             sub getMySQLDate(;@);
108             sub getFilelabelDate(;@);
109             sub getLogfileDate(;@);
110              
111             # Functional Class : logging
112             sub setDebugLevel($;$);
113             sub getDebugLevel();
114             sub setLogFile($;$);
115             sub getLogFile();
116             sub getErrorFile();
117             sub printDependInfo();
118             sub invalidateLogFILES();
119             sub cleanLogFILES();
120             sub closeLogERROR();
121             sub closeLogMSG();
122             sub openLogERROR();
123             sub openLogMSG();
124             sub logAppend($;$);
125             sub debugPush();
126             sub debugPop();
127             sub logLocal($$);
128             sub logError($;$);
129             sub bail($;$);
130              
131             # Functional Class : modified methods
132             sub TIGR_GetOptions(@);
133              
134             ## Implementation
135            
136              
137             # Functional Class : general
138              
139             =over
140              
141             =item $obj_instance = new TIGR::Foundation;
142              
143             This function creates a new instance of the TIGR::Foundation
144             object. A reference pointing to the object is returned on success. Otherwise,
145             this method returns undefined.
146              
147             =cut
148              
149              
150             sub new() {
151 0     0 1   my $self = {};
152 0           my $pkg = shift;
153              
154             # create the object
155 0           bless $self, $pkg;
156              
157             # Get the program name.
158 0           my $pname = basename($0, () );
159 0 0 0       if ( (defined ($pname) ) && ($pname =~ /^(.*)$/) ) {
160 0           $pname = $1;
161 0           $self->{program_name} = $pname ;
162             }
163 0 0         if ($self->{program_name} =~ /^-$/) { # check if '-' is the input
164 0           $self->{program_name} = "STDIN";
165             }
166             # Get the invocation.
167 0           my $pcommand = join (' ', @ARGV);
168 0 0         if ( defined $pcommand ) {
169 0           $pcommand =~ /^(.*)$/;
170 0           $pcommand = $1;
171             }
172             else {
173 0           $pcommand = "";
174             }
175 0           $self->{invocation} = $pcommand ;
176              
177             # The following variables are to contain information specified by
178             # the 'host' program; there are methods of setting and retrieving each.
179 0           @{$self->{depend_info}} = ();
  0            
180 0           $self->{version_handler} = undef;
181 0           $self->{version_info} = undef;
182 0           $self->{help_info} = undef;
183 0           $self->{usage_info} = undef;
184              
185             # These are used for logging.
186 0           $self->{debug_level} = -1; # debug is negative, no logging
187 0           @{$self->{debug_store}} = (); # the backup debug level stack
  0            
188 0           @{$self->{debug_queue}} = (); # queue used by MSG routine
  0            
189 0           @{$self->{error_queue}} = (); # queue used by ERROR routine
  0            
190 0           $self->{max_debug_queue_size} = 100; # maximum size for queue before
191             # log entries are expired
192 0           @{$self->{log_files}} = # these log files are consulted
  0            
193             ("$self->{program_name}.log", # on file write error and are
194             "/tmp/$self->{program_name}.$$.log"); # modified by setLogFile
195 0           $self->{msg_file_open_flag} = 0; # flag to check logLocal file
196 0           $self->{error_file_open_flag} = 0; # flag to check logError file
197 0           $self->{msg_file_used} = 0; # flag to indicate if log file
198 0           $self->{error_file_used} = 0; # has been written to
199 0           $self->{msg_append_flag} = 0; # by default logs are truncated
200 0           $self->{error_append_flag} = 0; # by default logs are truncated
201 0           $self->{log_append_setting} = 0; # (truncate == 0)
202 0           $self->{static_log_file} = undef; # user defined log file
203              
204             # These monitor program execution time.
205 0           $self->{start_time} = time; # program start time
206 0           $self->{finish_time} = undef; # program stop time
207            
208             # Set a user name and a host name.
209 0           $self->{'host_name'} = hostname();
210 0 0         if ( ! defined ( $self->{'host_name'} ) ) {
211 0           $self->{'host_name'} = "NOHOSTNAME";
212             }
213             else {
214 0           $self->{'host_name'} =~ s/^(\.*)$/$1/; # Taint-check it.
215             }
216              
217             # A __WARN__ handler is needed to keep this sane.
218 0   0       my $tmp_warn_handler = $SIG{__WARN__} || "DEFAULT";
219 0     0     $SIG{__WARN__} = sub {};
220 0           my @info_arr = getpwuid($<);
221 0           $self->{'user_name'} = $info_arr[0];
222 0           $self->{'home_dir'} = $info_arr[7];
223 0           $SIG{__WARN__} = $tmp_warn_handler;
224 0 0         if ( ! defined ( $self->{'user_name'} ) ) {
225 0           $self->{'user_name'} = "NOUSERNAME";
226             }
227             else {
228 0           $self->{'user_name'} =~ s/^(\.*)$/$1/g;# Taint check.
229             }
230 0 0         if ( ! defined ( $self->{'home_dir'} ) ) {
231 0           $self->{'home_dir'} = "/";
232             }
233             else {
234 0           $self->{'home_dir'} =~ s/^(\.*)$/$1/g; # Taint check.
235             }
236            
237             $self->logLocal("START: " . $self->{'program_name'} . " " .
238 0           $self->{'invocation'}, 0);
239 0           $self->logLocal("Username: " . $self->{'user_name'}, 0);
240 0           $self->logLocal("Hostname: " . $self->{'host_name'}, 0);
241              
242 0           return $self;
243             }
244              
245              
246              
247             =item $value = $obj_instance->getProgramInfo($field_type);
248              
249             This function returns field values for specified field types describing
250             attributes of the program. The C<$field_type> parameter must be a listed
251             attribute: C, C, C, C.
252             The C field specifies the bare name of the executable. The
253             C field specifies the command line arguments passed to the
254             executable. The C value returns the environment path to the
255             working directory. The C value specifies the absolute path to the
256             working directory. If C is found to be inconsistent, then that
257             value will return the C value. If an invalid C<$field_type> is
258             passed, the function returns undefined.
259              
260             =cut
261              
262              
263             sub getProgramInfo($) {
264 0     0 1   my $self = shift;
265 0           my $field_type = shift;
266 0           my $return_value = undef;
267 0 0         if (defined $field_type) {
268 0 0         $field_type =~ /^name$/ && do {
269 0           $return_value = $self->{program_name};
270             };
271 0 0         $field_type =~ /^invocation$/ && do {
272 0           $return_value = $self->{invocation};
273             };
274 0 0         $field_type =~ /^env_path$/ && do {
275 0           my $return_value = "";
276 0 0 0       if (
      0        
277             (defined $ENV{'PWD'}) &&
278             (abs_path($ENV{'PWD'}) eq abs_path(".") ) &&
279             ($ENV{'PWD'} =~ /^(.*)$/)
280             ) {
281 0           $ENV{'PWD'} = $1;
282 0           $return_value = $ENV{'PWD'};
283             }
284             else {
285 0           my $tmp_val = abs_path(".");
286              
287 0 0 0       if ( (defined ($tmp_val) ) && ($tmp_val =~ /^(.*)$/) ) {
288 0           $tmp_val = $1;
289 0           $return_value = $tmp_val;
290             }
291             }
292 0           return $return_value;
293             };
294              
295 0 0         $field_type =~ /^abs_path$/ && do {
296 0           my $tmp_val = abs_path(".");
297              
298 0 0 0       if ( (defined ($tmp_val) ) && ($tmp_val =~ /^(.*)$/) ) {
299 0           $tmp_val = $1;
300 0           $return_value = $tmp_val;
301             }
302             };
303             }
304 0           return $return_value;
305             }
306              
307             =item $exit_code = $obj_instance->runCommand($command_str);
308              
309             This function passes the argument C<$command_str> to /bin/sh
310             for processing. The return value is the exit code of the
311             C<$command_str>. If the exit code is not defined, then either the signal or
312             core dump value of the execution is returned, whichever is applicable. Perl
313             variables C<$?> and C<$!> are set accordingly. If C<$command_str> is not
314             defined, this function returns undefined. Log messages are recorded at log
315             level 4 to indicate the type of exit status and the corresponding code.
316             A failure to start the program (invalid program) results in return code -1.
317              
318             =cut
319              
320              
321             sub runCommand($) {
322 0     0 1   my $self = shift;
323 0           my $command_str = shift;
324 0           my $exit_code = undef;
325 0           my $signal_num = undef;
326 0           my $dumped_core = undef;
327 0           my $return_value = undef;
328 0           my $current_dir = $self->getProgramInfo("abs_path");
329            
330             # Return if the command string is not set.
331 0 0         if ( ! defined ( $command_str ) ) {
332 0           return undef;
333             }
334              
335             # Substitute out the tilde and dot in the directory paths.
336 0 0         if ( defined ($ENV{PATH}) ) {
337 0           ( $ENV{PATH} ) = $ENV{PATH} =~ /^(.*)$/;
338 0           my @paths = split /:/, $ENV{PATH};
339 0           for (my $i = 0; $i <= $#paths; $i++) {
340 0           $paths[$i] =~ s/^~\/?$/$self->{'home_dir'}/g;
341 0           $paths[$i] =~ s/^\.\/?$/$current_dir/g;
342             }
343 0           $ENV{PATH} = join(":", @paths);
344             }
345              
346 0           $command_str =~ s/^(.*)$/$1/g; # Taint checking.
347             # Run the command and parse the results.
348 0           system($command_str);
349 0           my $return_str = $?;
350 0           $exit_code = $? >> 8;
351 0           $signal_num = $? & 127;
352 0           $dumped_core = $? & 128;
353 0 0         if ( $return_str == -1 ) { # Check for invalid program.
    0          
    0          
354 0           $self->logLocal("Invalid execution of \'$command_str\'.", 4);
355 0           $return_value = -1;
356             }
357             elsif ( $dumped_core != 0 ) {
358 0           $self->logLocal("\'$command_str\' dumped core.", 4);
359 0           $return_value = $dumped_core;
360             }
361             elsif ( $signal_num != 0 ) {
362 0           $self->logLocal("\'$command_str\' signalled \'$signal_num\'.", 4);
363 0           $return_value = $signal_num;
364             }
365             else {
366 0           $self->logLocal("\'$command_str\' exited \'$exit_code\'.", 4);
367 0           $return_value = $exit_code;
368             }
369 0           return $return_value;
370             }
371            
372              
373             # Functional Class : depend
374              
375             =item $obj_instance->printDependInfo();
376              
377             The C function prints the dependency list created by
378             C. One item is printed per line.
379              
380             =cut
381              
382              
383             sub printDependInfo() {
384 0     0 1   my $self = shift;
385 0           foreach my $dependent (@{$self->{depend_info}}) {
  0            
386 0           print STDERR $dependent, "\n";
387             }
388             }
389              
390              
391             =item $obj_instance->printDependInfoAndExit();
392              
393             The C function prints the dependency list created by
394             C. One item is printed per line. The function exits with
395             exit code 0.
396              
397             =cut
398              
399              
400             sub printDependInfoAndExit() {
401 0     0 1   my $self = shift;
402 0           $self->printDependInfo();
403 0           exit 0;
404             }
405              
406              
407             =item $obj_instance->addDependInfo(@depend_list);
408              
409             The C function adds C<@depend_list> information
410             to the dependency list. If C<@depend_list> is empty, the internal
411             dependency list is emptied. Contents of C<@depend_list> are not checked
412             for validity (eg. they can be composed entirely of white space or
413             multiple files per record). The first undefined record in C<@depend_list>
414             halts reading in of dependency information.
415              
416             =cut
417              
418              
419             sub addDependInfo(@) {
420 0     0 1   my $self = shift;
421 0           my $num_elts = 0;
422 0           while (my $data_elt = shift @_) {
423 0           push (@{$self->{depend_info}}, $data_elt);
  0            
424 0           $num_elts++;
425             }
426 0 0         if ($num_elts == 0) {
427 0           @{$self->{depend_info}} = ();
  0            
428             }
429             }
430              
431              
432             # Functional Class : version
433              
434             =item $version_string = $obj_instance->getVersionInfo();
435              
436             The C function returns the version information set by the
437             C function.
438              
439             =cut
440              
441              
442             sub getVersionInfo() {
443 0     0 1   my $self = shift;
444 0           return $self->{version_info};
445             }
446              
447              
448             =item $obj_instance->printVersionInfo();
449              
450             The C function calls the version handler, if set. If not,
451             it prints the version information set by the C function.
452             If there is no defined version information, a message is returned notifying
453             the user.
454              
455             =cut
456              
457              
458             sub printVersionInfo() {
459 0     0 1   my $self = shift;
460 0 0         if ( defined $self->{'version_handler'} ) {
    0          
461 0           $self->{'version_handler'}->();
462             }
463             elsif (defined $self->getVersionInfo() ) {
464 0           print STDERR $self->getProgramInfo('name'), " ",
465             $self->getVersionInfo(), "\n";
466             }
467             else {
468 0           print STDERR $self->getProgramInfo('name'),
469             " has no defined version information\n";
470             }
471             }
472              
473              
474             =item $obj_instance->printVersionInfoAndExit();
475              
476             The C function calls the version handler, if set.
477             Otherwise, it prints prints version info set by the C
478             function. If there is no defined version information, a message is printed
479             notifying the user. This function calls exit with exit code 0.
480              
481             =cut
482              
483              
484             sub printVersionInfoAndExit() {
485 0     0 1   my $self = shift;
486 0           $self->printVersionInfo();
487 0           exit 0;
488             }
489              
490              
491             =item $obj_instance->setVersionInfo($version_string);
492              
493             The C function sets the version information to be reported
494             by C. If C<$version_string> is empty, invalid, or
495             undefined, the stored version information will be undefined.
496              
497             =cut
498              
499              
500             sub setVersionInfo($) {
501 0     0 1   my $self = shift;
502 0           my $v_info = shift;
503 0 0 0       if ( defined ( $v_info ) && ( $v_info =~ /\S/ ) ) {
504 0           $self->{version_info} = $v_info;
505             }
506             else {
507 0           $self->{version_info} = undef;
508             }
509             }
510              
511              
512             =item $obj_instance->setVersionHandler($function_ref);
513              
514             The C method establishes a callback function for handling
515             the reporting of version information to the user. If a handler is set, then
516             any information passed in via C is not reported. To
517             remove the handler, call this method without any arguments. If a handler is
518             not a proper code reference, this method returns undefined and does not set
519             a handler. This method returns 1 on success.
520              
521             =cut
522              
523              
524             sub setVersionHandler($) {
525 0     0 1   my $self = shift;
526 0           my $v_handler = shift;
527 0 0 0       if ( defined ( $v_handler ) && ( (ref $v_handler) eq "CODE" ) ) {
    0          
528 0           $self->{version_handler} = $v_handler;
529             }
530             elsif ( ! defined ( $v_handler ) ) {
531 0           $self->{version_handler} = undef;
532             }
533             else {
534             # Bad input.
535 0           return undef;
536             }
537 0           return 1;
538             }
539              
540              
541             # Functional Class : help
542              
543             =item $obj_instance->printHelpInfo();
544              
545             The C function prints the help information passed by the
546             C function.
547              
548             =cut
549              
550              
551             sub printHelpInfo() {
552 0     0 1   my $self = shift;
553 0 0         if (defined $self->{help_info}) {
554 0           print STDERR $self->{help_info};
555             }
556             else {
557 0           print STDERR "No help information defined.\n";
558             }
559             }
560              
561              
562             =item $obj_instance->printHelpInfoAndExit();
563              
564             The C function prints the help info passed by the
565             C function. This function exits with exit code 0.
566              
567             =cut
568              
569              
570             sub printHelpInfoAndExit() {
571 0     0 1   my $self = shift;
572 0           $self->printHelpInfo();
573 0           exit 0;
574             }
575              
576              
577             =item $obj_instance->setHelpInfo($help_string);
578              
579             The C function sets the help information via C<$help_string>.
580             If C<$help_string> is undefined, invalid, or empty, the help information
581             is undefined.
582              
583             =cut
584              
585              
586             sub setHelpInfo($) {
587 0     0 1   my $self = shift;
588 0           my $help_string = shift;
589 0 0 0       if ( ( defined $help_string ) && ( $help_string =~ /\S/ ) ) {
590 0           chomp $help_string;
591 0           $self->{help_info} = $help_string . "\n";
592             }
593             else {
594 0           $self->{help_info} = undef;
595             }
596             }
597              
598              
599             # Functional Class : usage
600              
601             =item $obj_instance->printUsageInfo();
602              
603             The C function prints the usage information reported by the
604             C function. If no usage information is defined, but help
605             information is defined, help information will be printed.
606              
607             =cut
608              
609              
610             sub printUsageInfo() {
611            
612 0     0 1   my $self = shift;
613 0 0         if ( defined $self->{usage_info} ) {
    0          
614 0           print STDERR $self->{usage_info};
615             }
616             elsif ( defined $self->{help_info} ) {
617 0           print STDERR $self->{help_info};
618             }
619             else {
620 0           print STDERR "No usage information defined.\n";
621             }
622             }
623              
624              
625             =item $obj_instance->printUsageInfoAndExit();
626              
627             The C function prints the usage information the
628             reported by the C function and exits with status 1.
629              
630             =cut
631              
632              
633             sub printUsageInfoAndExit() {
634 0     0 1   my $self = shift;
635 0           $self->printUsageInfo();
636 0           exit 1;
637             }
638              
639              
640             =item $obj_instance->setUsageInfo($usage_string);
641              
642             The C function sets the usage information via C<$usage_string>.
643             If C<$usage_string> is undefined, invalid, or empty, the usage information
644             is undefined.
645              
646             =cut
647              
648              
649             sub setUsageInfo($) {
650 0     0 1   my $self = shift;
651 0           my $usage_string = shift;
652 0 0 0       if ( ( defined $usage_string ) && ( $usage_string =~ /\S/ ) ) {
653 0           chomp($usage_string);
654 0           $self->{usage_info} = $usage_string . "\n";
655             }
656             else {
657 0           $self->{usage_info} = undef;
658             }
659             }
660              
661              
662             # Functional Class : files
663              
664             =item $valid = isReadableFile($file_name);
665              
666             This function accepts a single scalar parameter containing a file name.
667             If the file corresponding to the file name is a readable plain file or symbolic
668             link, this function returns 1. Otherwise, the function returns 0. If the file
669             name passed is undefined, this function returns 0 as well.
670              
671             =cut
672              
673              
674             sub isReadableFile($) {
675 0     0 1   my $self = shift;
676 0           my $file = shift;
677 0 0         if ( ! defined ( $file ) ) { # class, not instance, invocation
678 0           $file = $self;
679             }
680            
681 0 0 0       if (defined ($file) && # was a file name passed?
      0        
      0        
682             ( (-f $file) || (-l $file) ) && # is the file a file or sym. link?
683             (-r $file) # is the file readable?
684             ) {
685 0           return 1;
686             }
687             else {
688 0           return 0;
689             }
690             }
691              
692              
693             =item $valid = isExecutableFile($file_name);
694              
695             This function accepts a single scalar parameter containing a file name.
696             If the file corresponding to the file name is an executable plain file
697             or symbolic link, this function returns 1. Otherwise, the function returns 0.
698             If the file name passed is undefined, this function returns 0 as well.
699              
700             =cut
701              
702              
703             sub isExecutableFile($) {
704 0     0 1   my $self = shift;
705 0           my $file = shift;
706 0 0         if ( ! defined ( $file ) ) { # class invocation, not instance
707 0           $file = $self;
708             }
709            
710 0 0 0       if (defined ($file) && # was a file name passed?
      0        
      0        
711             ( (-f $file) || (-l $file) ) && # is the file a file or sym. link?
712             (-x $file) # is the file executable?
713             ) {
714 0           return 1;
715             }
716             else {
717 0           return 0;
718             }
719             }
720              
721              
722             =item $valid = isWritableFile($file_name);
723              
724             This function accepts a single scalar parameter containing a file name.
725             If the file corresponding to the file name is a writable plain file
726             or symbolic link, this function returns 1. Otherwise, the function returns 0.
727             If the file name passed is undefined, this function returns 0 as well.
728              
729             =cut
730              
731              
732             sub isWritableFile($) {
733 0     0 1   my $self = shift;
734 0           my $file = shift;
735 0 0         if ( ! defined ( $file ) ) { # class, not instance, invocation
736 0           $file = $self;
737             }
738            
739 0 0 0       if (defined ($file) && # was a file name passed?
      0        
      0        
740             ( (-f $file) || (-l $file) ) && # is the file a file or sym. link?
741             (-w $file) # is the file writable?
742             ) {
743 0           return 1;
744             }
745             else {
746 0           return 0;
747             }
748             }
749              
750              
751             =item $valid = isCreatableFile($file_name);
752              
753             This function accepts a single scalar parameter containing a file name. If
754             the file corresponding to the file name is creatable this function returns 1.
755             The function checks if the location of the file is writable by the effective
756             user id (EUID). If the file location does not exist or the location is not
757             writable, the function returns 0. If the file name passed is undefined,
758             this function returns 0 as well. Note that files with suffix F are not
759             supported under UNIX platforms, and will return 0.
760              
761             =cut
762              
763              
764             sub isCreatableFile($) {
765 0     0 1   my $self = shift;
766 0           my $file = shift;
767 0 0         if ( ! defined ( $file ) ) {
768 0           $file = $self;
769             }
770 0           my $return_code = 0;
771 0 0 0       if (
      0        
772             (defined ($file) ) &&
773             (! -e $file) &&
774             ($file !~ /\/$/)
775             ) {
776 0           my $dirname = dirname($file);
777             # check the writability of the directory
778 0           $return_code = isWritableDir($dirname);
779             }
780             else {
781             # the file exists, it's not creatable
782 0           $return_code = 0;
783             }
784 0           return $return_code;
785             }
786              
787              
788             =item $valid = isReadableDir($directory_name);
789              
790             This function accepts a single scalar parameter containing a directory name.
791             If the name corresponding to the directory is a readable, searchable directory
792             entry, this function returns 1. Otherwise, the function returns 0. If the
793             name passed is undefined, this function returns 0 as well.
794              
795             =cut
796              
797              
798             sub isReadableDir($) {
799 0     0 1   my $self = shift;
800 0           my $file = shift;
801 0 0         if ( ! defined ( $file ) ) { # class invocation
802 0           $file = $self;
803             }
804            
805 0 0 0       if (defined ($file) && # was a name passed?
      0        
      0        
806             (-d $file) && # is the name a directory?
807             (-r $file) && # is the directory readable?
808             (-x $file) # is the directory searchable?
809             ) {
810 0           return 1;
811             }
812             else {
813 0           return 0;
814             }
815             }
816              
817              
818             =item $valid = isWritableDir($directory_name);
819              
820             This function accepts a single scalar parameter containing a directory name.
821             If the name corresponding to the directory is a writable, searchable directory
822             entry, this function returns 1. Otherwise, the function returns 0. If the
823             name passed is undefined, this function returns 0 as well.
824              
825             =cut
826              
827              
828             sub isWritableDir($) {
829 0     0 1   my $self = shift;
830 0           my $file = shift;
831 0 0         if ( ! defined ( $file ) ) { # class invocation
832 0           $file = $self;
833             }
834            
835 0 0 0       if (defined ($file) && # was a name passed?
      0        
      0        
836             (-d $file) && # is the name a directory?
837             (-w $file) && # is the directory writable?
838             (-x $file) # is the directory searchable?
839             ) {
840 0           return 1;
841             }
842             else {
843 0           return 0;
844             }
845             }
846              
847              
848             =item $valid = isCreatableDir($directory_name);
849              
850             This function accepts a single scalar parameter containing a directory name.
851             If the name corresponding to the directory is creatable this function returns
852             1. The function checks if the immediate parent of the directory is writable by
853             the effective user id (EUID). If the parent directory does not exist or the
854             tree is not writable, the function returns 0. If the directory name passed is
855             undefined, this function returns 0 as well.
856              
857             =cut
858              
859              
860             sub isCreatableDir($) {
861 0     0 1   my $self = shift;
862 0           my $dir = shift;
863 0 0         if ( ! defined ( $dir ) ) {
864 0           $dir = $self;
865             }
866 0           my $return_code = 0;
867              
868 0 0         if (defined ($dir) ) {
869 0           $dir =~ s/\/$//g;
870 0           $return_code = isCreatableFile($dir);
871             }
872 0           return $return_code;
873             }
874              
875              
876             =item $valid = isCreatablePath($path_name);
877              
878             This function accepts a single scalar parameter containing a path name. If
879             the C<$path_name> is creatable this function returns 1. The function checks
880             if the directory hierarchy of the path is creatable or writable by the
881             effective user id (EUID). This function calls itself recursively until
882             an existing directory node is found. If that node is writable, ie. the path
883             can be created in it, then this function returns 1. Otherwise, the function
884             returns 0. This function also returns zero if the C<$path_name> supplied
885             is disconnected from a reachable directory tree on the file system.
886             If the path already exists, this function returns 0. The C<$path_name> may
887             imply either a path to a file or a directory. Path names may be relative or
888             absolute paths. Any unresolvable relative paths will return 0 as well. This
889             includes paths with F<..> back references to nonexistent directories.
890             This function is recursive whereas C and
891             C are not.
892              
893             =cut
894              
895              
896             sub isCreatablePath($) {
897 0     0 1   my $self = shift;
898 0           my $pathname = shift;
899 0 0         if ( ! defined ( $pathname ) ) { # class invocation
900 0           $pathname = shift;
901             }
902 0           my $return_code = 0;
903              
904 0 0         if (defined $pathname) {
905             # strip trailing '/'
906 0           $pathname =~ s/(.+)\/$/$1/g;
907 0           my $filename = basename($pathname);
908 0           my $dirname = dirname($pathname);
909 0 0 0       if (
      0        
910             (! -e $pathname) &&
911             ($dirname ne $pathname) &&
912             ($filename ne "..")
913             ) {
914 0 0         if (-e $dirname) {
915 0           $return_code = isWritableDir($dirname);
916             }
917             else {
918 0           $return_code = isCreatablePath($dirname);
919             }
920             }
921             else {
922 0           $return_code = 0;
923             }
924             }
925 0           return $return_code;
926             }
927            
928              
929             # Functional Class : date
930              
931             =item $date_string = getISODate($tm);
932              
933             This function returns the ISO 8601 datetime as a string given a time
934             structure as returned by the C
935             are supplied, this function returns the current time. If incorrect
936             arguments are supplied, this function returns undefined.
937              
938             =cut
939              
940              
941             sub getISODate(;@) {
942             #checking if the function is invoked as an instance method.
943 0 0 0 0 1   if ( (defined(ref $_[0]) ) && ( (ref $_[0]) eq "TIGR::Foundation") ){
944 0           shift;
945             }
946 0           my @time_val = @_;
947 0           my $time_str = undef;
948 0 0         if (scalar(@time_val) == 0) {
949 0           @time_val = localtime;
950             }
951 0           eval {
952 0           $time_str = strftime "%Y-%m-%d %H:%M:%S", @time_val;
953             };
954 0           return $time_str;
955             }
956              
957              
958             =item $date_string = getSybaseDate(@tm);
959              
960             This function returns a Sybase formatted datetime as a string given a time
961             structure as returned by the C
962             are supplied, this function returns the current time. If incorrect
963             arguments are supplied, this function returns undefined. The date string
964             returned is quoted according to Sybase requirements.
965              
966             =cut
967              
968              
969             sub getSybaseDate(;@) {
970             #checking if the function is invoked as an instance method.
971 0 0 0 0 1   if ( (defined(ref $_[0]) ) && ( (ref $_[0]) eq "TIGR::Foundation") ){
972 0           shift;
973             }
974 0           my @time_val = @_;
975 0           my $time_str = undef;
976 0 0         if (scalar(@time_val) == 0) {
977 0           @time_val = localtime;
978             }
979 0           eval {
980 0           $time_str = strftime "\'%b %d %Y %I:%M%p\'", @time_val;
981             };
982 0           return $time_str;
983             }
984            
985              
986             =item $date_string = getMySQLDate(@tm);
987              
988             This function returns a MySQL formatted datetime as a string given a time
989             structure as returned by the C
990             are supplied, this function returns the current time. If incorrect
991             arguments are supplied, this function returns undefined. The datetime string
992             returned is prequoted according to MySQL requirements.
993              
994             =cut
995              
996              
997             sub getMySQLDate(;@) {
998             #checking if the function is invoked as an instance method.
999 0 0 0 0 1   if ( (defined(ref $_[0]) ) && ( (ref $_[0]) eq "TIGR::Foundation") ){
1000 0           shift;
1001             }
1002 0           my @time_val = @_;
1003 0           my $time_str = undef;
1004 0 0         if (scalar(@time_val) == 0) {
1005 0           @time_val = localtime;
1006             }
1007 0           $time_str = getISODate(@time_val);
1008 0 0         if (defined $time_str) {
1009 0           $time_str = "\'$time_str\'";
1010             }
1011 0           return $time_str;
1012             }
1013            
1014              
1015             =item $date_string = getFilelabelDate(@tm);
1016              
1017             This function returns the date (not time) as a compressed string
1018             suitable for use as part of a file name. The format is YYMMDD.
1019             The optional parameter should be a time structure as returned by
1020             the C
1021             is used. If incorrect arguments are supplied, this function returns
1022             undefined.
1023              
1024             =cut
1025              
1026              
1027             sub getFilelabelDate(;@) {
1028             #checking if the function is invoked as an instance method.
1029 0 0 0 0 1   if ( (defined(ref $_[0]) ) && ( (ref $_[0]) eq "TIGR::Foundation") ){
1030 0           shift;
1031             }
1032 0           my @time_val = @_;
1033 0           my $time_str = undef;
1034 0 0         if (scalar(@time_val) == 0) {
1035 0           @time_val = localtime;
1036             }
1037 0           eval {
1038 0           $time_str = strftime "%y%m%d", @time_val;
1039             };
1040 0           return $time_str;
1041             }
1042            
1043              
1044             =item $date_string = $obj_instance->getLogfileDate(@tm);
1045              
1046             This function returns the datetime as a formatted string
1047             suitable for use as a log entry header. The optional parameter
1048             should be a time structure as returned by the C
1049             If no arguments are supplied, this function uses the current time.
1050             If incorrect arguments are supplied, this function sets the date/time fields
1051             of the log entry string to C< INVALID|XXXXXX|>.
1052              
1053             =cut
1054              
1055              
1056             sub getLogfileDate(;@) {
1057             #checking if the function is invoked as an instance method.
1058 0 0 0 0 1   if ( (defined(ref $_[0]) ) && ( (ref $_[0]) eq "TIGR::Foundation") ){
1059 0           shift;
1060             }
1061 0           my @time_val = @_;
1062 0           my $time_str = undef;
1063 0           my $log_form = undef;
1064 0 0         if (scalar(@time_val) == 0) {
1065 0           @time_val = localtime;
1066             }
1067 0           eval {
1068 0           $time_str = strftime("%Y%m%d|%H%M%S|", @time_val);
1069             };
1070 0 0         if (!defined $time_str) {
1071 0           $time_str = " INVALID|XXXXXX|";
1072             }
1073 0           $log_form = $time_str . sprintf("%6d| ", $$);
1074 0           return $log_form;
1075             }
1076            
1077              
1078             # Functional Class : logging
1079              
1080             =item $obj_instance->setDebugLevel($new_level);
1081              
1082             This function sets the level of debug reporting according to C<$new_level>.
1083             If C<$new_level> is less than 0, all debug reporting is turned off and
1084             C will report undefined. If C<$new_level> is not specified,
1085             the debug level is set to 0. For compatibility, this function will also accept
1086             the debug level as the second parameter. In such cases, the first parameter
1087             is checked only if the second parameter is invalid. By default, the debug
1088             level is undefined.
1089              
1090             =cut
1091              
1092              
1093             sub setDebugLevel($;$) {
1094 0     0 1   my $self = shift;
1095 0           my $new_level = shift;
1096 0           my $getopts_new_level = shift;
1097              
1098 0 0 0       if (
    0 0        
1099             (defined $getopts_new_level) &&
1100             ($getopts_new_level =~ /^-?\d+$/)
1101             ) {
1102 0           $new_level = $getopts_new_level;
1103             }
1104             elsif (
1105             (!defined $new_level) ||
1106             ($new_level !~ /^-?\d+$/)
1107             ) {
1108 0           $new_level = 0;
1109 0           $self->logLocal("No or invalid parameter to setDebugLevel(), " .
1110             "setting debug level to 0", 3);
1111             }
1112              
1113 0 0         if ($new_level < 0) {
1114 0           $new_level = -1;
1115             }
1116              
1117 0           $self->{debug_level} = $new_level;
1118 0           my $level = $self->getDebugLevel();
1119 0 0         if ( ! defined ( $level ) ) { $level = ""; }
  0            
1120 0           $self->logLocal("Set debug level to " . $level, 2);
1121             }
1122              
1123              
1124             =item $level = $obj_instance->getDebugLevel();
1125              
1126             This function returns the current debug level. If the debug level has
1127             not been set, this method returns .
1128              
1129             =cut
1130              
1131              
1132             sub getDebugLevel() {
1133 0     0 1   my $self = shift;
1134 0 0         if ( $self->{'debug_level'} == -1 ) {
1135 0           return undef;
1136             }
1137             else {
1138 0           return $self->{'debug_level'};
1139             }
1140             }
1141              
1142              
1143             =item $obj_instance->setLogFile($log_file);
1144              
1145             This function sets the log file name for use by the C function.
1146             B>
1147             if the default log file is not to be used. The new log file name is the
1148             only parameter. Future calls to C or C log to C<$log_file>
1149             if it is successfully opened. If the new log file is not successfully opened,
1150             the function will try to open the default log file, F.
1151             If that file cannot be opened, F will
1152             be used. If no parameter is passed, this method does nothing. For
1153             compatibility, this method accepts the second parameter as the log file. The
1154             first parameter is ignored in such cases. B log files (including the
1155             defailt log file) with relative paths will track with program execution
1156             whenever a change of directory is made.
1157              
1158             =cut
1159              
1160              
1161             sub setLogFile($;$) {
1162 0     0 1   my $self = shift;
1163             my $old_log_file = defined $self->{static_log_file} ?
1164 0 0         $self->{static_log_file} : undef;
1165 0           $self->{static_log_file} = shift;
1166 0 0         if (scalar(@_) == 1) {
1167 0           $self->{static_log_file} = shift;
1168             }
1169              
1170             # only consider a new log file that is definable as a file
1171 0 0 0       if ( (defined ($self->{static_log_file}) ) &&
1172             ($self->{static_log_file} !~ /^\s*$/) ) {
1173             # delete an old log file entry added by "setLogFile"
1174 0   0       for (my $idx = 0;
1175 0           ($idx <= $#{$self->{log_files}}) && defined($old_log_file);
1176             $idx++) {
1177 0 0         if ($self->{log_files}[$idx] eq $old_log_file) {
1178 0           splice @{$self->{log_files}}, $idx, 1;
  0            
1179 0           $old_log_file = undef;
1180             }
1181             }
1182 0           unshift @{$self->{log_files}}, $self->{static_log_file};
  0            
1183              
1184             # initialize the log file variables and file spaces
1185 0           $self->{msg_file_used} = 0;
1186 0           $self->{error_file_used} = 0;
1187 0           $self->cleanLogFILES();
1188             }
1189             }
1190              
1191              
1192             =item $log_file_name = $obj_instance->getLogFile();
1193              
1194             This function returns the name of the log file to be used for printing
1195             log messages. We return undefined if there are no more log files to bind.
1196              
1197             =cut
1198              
1199              
1200             sub getLogFile() {
1201 0     0 1   my $self = shift;
1202 0           return $self->{log_files}[0];
1203             }
1204              
1205              
1206             =item $error_file_name = $obj_instance->getErrorFile();
1207              
1208             This function returns the name of the error file to be used for printing
1209             error messages. The error file is derived from the log file; a F<.log>
1210             extension is replaced by a F<.error> extension. If there is no F<.log>
1211             extension, then F<.error> is appended to the log file name. We return
1212             undefined if there are no more log files to bind.
1213              
1214             =cut
1215              
1216              
1217             sub getErrorFile() {
1218 0     0 1   my $self = shift;
1219 0           my $return_val = $self->getLogFile();
1220 0 0         if ( defined ( $return_val ) ) {
1221 0           $return_val =~ s/\.log$//g;
1222 0           $return_val .= '.error';
1223             }
1224 0           return $return_val;
1225             }
1226              
1227              
1228             # the following private functions are used for logging
1229              
1230              
1231             # push items onto the debug level stack
1232             sub debugPush() {
1233 0     0 0   my $self = shift;
1234 0           push @{$self->{debug_store}}, $self->{debug_level};
  0            
1235 0           $self->{debug_level} = -1;
1236             }
1237              
1238              
1239             # pop items from the debug level stack
1240             sub debugPop() {
1241 0     0 0   my $self = shift;
1242 0           $self->{debug_level} = pop @{$self->{debug_store}};
  0            
1243             }
1244              
1245              
1246             # remove log files
1247             sub removeLogERROR() {
1248            
1249 0     0 0   my $self = shift;
1250 0           $self->debugPush();
1251 0 0 0       if (
1252             (defined $self->getErrorFile() ) &&
1253             (isWritableFile($self->getErrorFile() ))
1254             ) {
1255 0 0         unlink $self->getErrorFile() or
1256             $self->logLocal("Unable to remove error file " .
1257             $self->getErrorFile(), 3);
1258             }
1259 0           $self->debugPop();
1260             }
1261              
1262              
1263             sub removeLogMSG() {
1264 0     0 0   my $self = shift;
1265 0           $self->debugPush();
1266            
1267 0 0 0       if (
1268             (defined $self->getLogFile() ) &&
1269             (isWritableFile($self->getLogFile() ))
1270             ) {
1271 0 0         unlink $self->getLogFile() or
1272             $self->logLocal("Unable to remove error file " .
1273             $self->getLogFile(), 3);
1274             }
1275 0           $self->debugPop();
1276             }
1277              
1278              
1279             # invalidate log files
1280             sub invalidateLogFILES() {
1281 0     0 0   my $self = shift;
1282 0           $self->debugPush();
1283 0 0         if (defined $self->getLogFile() ) {
1284 0           $self->logLocal("Invalidating " . $self->getLogFile(), 2);
1285 0           shift @{$self->{log_files}};
  0            
1286             $self->{msg_append_flag} = $self->{error_append_flag} =
1287 0           $self->{log_append_setting};
1288 0           $self->{msg_file_used} = $self->{error_file_used} = 0;
1289 0           $self->cleanLogFILES();
1290             }
1291 0           $self->debugPop();
1292             }
1293              
1294              
1295             # clean previous log files
1296             sub cleanLogFILES() {
1297 0     0 0   my $self = shift;
1298 0 0         if ($self->{log_append_setting} == 0) {
1299 0 0         if ($self->{msg_file_used} == 0) {
1300 0           $self->removeLogMSG();
1301             }
1302 0 0         if ($self->{error_file_used} == 0) {
1303 0           $self->removeLogERROR();
1304             }
1305             }
1306             }
1307              
1308              
1309             # close log files
1310             sub closeLogERROR() {
1311 0     0 0   my $self = shift;
1312 0           my $return_code = 1; # need to return true for success, false for fail
1313              
1314 0           $self->debugPush();
1315 0 0 0       if (!close(ERRLOG) && (defined $self->getErrorFile() )) {
1316 0           $self->logLocal("Cannot close " . $self->getErrorFile(), 3);
1317 0           $return_code = 0;
1318             }
1319             else {
1320 0           $return_code = 1;
1321             }
1322 0           $self->{error_file_open_flag} = 0;
1323 0           $self->debugPop();
1324 0           return $return_code;
1325             }
1326              
1327              
1328             sub closeLogMSG() {
1329 0     0 0   my $self = shift;
1330 0           my $return_code = 1; # need to return true for success, false for fail
1331              
1332 0           $self->debugPush();
1333 0 0 0       if (!close(MSGLOG) && (defined $self->getLogFile() )) {
1334 0           $self->logLocal("Cannot close " . $self->getLogFile(), 3);
1335 0           $return_code = 0;
1336             }
1337             else {
1338 0           $return_code = 1;
1339             }
1340 0           $self->{msg_file_open_flag} = 0;
1341 0           $self->debugPop();
1342 0           return $return_code;
1343             }
1344              
1345              
1346             # open log files
1347             sub openLogERROR() {
1348 0     0 0   my $self = shift;
1349 0           my $return_code = 1; # need to return true for success, false for fail
1350              
1351 0           $self->debugPush();
1352 0 0 0       if ( (defined $self->getErrorFile() ) &&
1353             ($self->{error_file_open_flag} == 0) ) {
1354 0           my $fileop;
1355 0           $self->{error_file_open_flag} = 1;
1356 0 0         if ($self->{error_append_flag} == 0) {
1357 0           $fileop = '>';
1358 0           $self->{error_append_flag} = 1;
1359             }
1360             else {
1361 0           $fileop = '>>';
1362             }
1363 0 0         if (open(ERRLOG, $fileop . $self->getErrorFile() )) {
1364 0           autoflush ERRLOG 1;
1365             }
1366             else {
1367 0           $self->logLocal("Cannot open " . $self->getErrorFile() .
1368             " for logging", 4);
1369 0           $self->{error_file_open_flag} = 0;
1370             }
1371             }
1372 0           $return_code = $self->{error_file_open_flag};
1373 0           $self->debugPop();
1374              
1375             # this is 1 if the file stream is open, 0 if not
1376 0           return $return_code;
1377             }
1378              
1379              
1380             sub openLogMSG() {
1381 0     0 0   my $self = shift;
1382 0           my $return_code = 1; # need to return true for success, false for fail
1383              
1384 0           $self->debugPush();
1385 0 0 0       if ( (defined $self->getLogFile() ) &&
1386             ($self->{msg_file_open_flag} == 0) ) {
1387 0           my $fileop;
1388 0           $self->{msg_file_open_flag} = 1;
1389 0 0         if ($self->{msg_append_flag} == 0) {
1390 0           $fileop = '>';
1391 0           $self->{msg_append_flag} = 1;
1392             }
1393             else {
1394 0           $fileop = '>>';
1395             }
1396              
1397 0 0         if (open(MSGLOG, $fileop . $self->getLogFile() )) {
1398 0           autoflush MSGLOG 1;
1399             }
1400             else {
1401 0           $self->logLocal("Cannot open " . $self->getLogFile() .
1402             " for logging", 4);
1403 0           $self->{msg_file_open_flag} = 0;
1404             }
1405             }
1406 0           $return_code = $self->{msg_file_open_flag};
1407 0           $self->debugPop();
1408              
1409             # this is 1 if the file stream is open, 0 if not
1410 0           return $return_code;
1411             }
1412              
1413              
1414             =item $obj_instance->logAppend($log_append_flag);
1415              
1416             Passing C<0> signals truncation of log files while C<1> signals appending.
1417             By default, log files are truncated at the start of program execution or
1418             logging. Error files are controlled by this method as well. Any truncation
1419             occurs before the next write. For compatibility, this method accepts and
1420             prefers a second parameter argument for the log-append flag.
1421              
1422             =cut
1423              
1424              
1425             sub logAppend($;$) {
1426 0     0 1   my $self = shift;
1427 0           my $log_append_flag = shift;
1428 0 0         if (defined $_[0]) {
1429 0           $log_append_flag = shift;
1430             }
1431 0 0 0       if (
      0        
1432             (defined ($log_append_flag) ) &&
1433             ( ($log_append_flag eq "0") ||
1434             ($log_append_flag eq "1") )
1435             ) {
1436             $self->{log_append_setting} = $self->{msg_append_flag} =
1437 0           $self->{error_append_flag} = $log_append_flag;
1438             }
1439             }
1440              
1441              
1442             =item $obj_instance->logLocal($log_message, $log_level);
1443              
1444             The C function takes two arguments. The C<$log_message>
1445             argument specifies the message to be written to the log file. The
1446             C<$log_level> argument specifies the level at which C<$log_message> is printed.
1447             The active level of logging is set via the C function.
1448             Only messages at C<$log_level> less than or equal to the active debug
1449             level are logged. The default debug level is undefined (no logging). Note, a
1450             trailing new line, if it exists, is stripped from the log message.
1451              
1452             =cut
1453              
1454              
1455             sub logLocal($$) {
1456 0     0 1   my $self = shift;
1457 0           my $log_message = shift;
1458 0           my $log_level = shift;
1459              
1460 0 0 0       if ( ( ! defined $log_level ) || ( $log_level =~ /\D/ ) ) {
1461 0           $log_level = 1;
1462             }
1463              
1464 0 0         if (defined $log_message) {
1465 0           chomp $log_message; # strip end new line, if it exists
1466 0           $log_message = getLogfileDate() . $log_message;
1467 0           push @{$self->{debug_queue}}, [ $log_message, $log_level ];
  0            
1468 0 0         if ( $self->{'debug_level'} >= 0 ) {
1469 0   0       while ( defined ( my $log_record = $self->{debug_queue}[0] ) &&
1470             defined ( $self->getLogFile() ) ) {
1471 0           ( $log_message, $log_level ) = @{$log_record};
  0            
1472 0 0 0       if (
      0        
      0        
      0        
      0        
1473             (
1474             ($log_level <= $self->{'debug_level'} ) && # debug level
1475             ($self->openLogMSG() ) && # check log file
1476             (print MSGLOG "$log_message\n") && # print message
1477             ($self->closeLogMSG() ) && # close log file
1478             ($self->{msg_file_used} = 1) # log file used
1479             ) ||
1480             (
1481             ($log_level > $self->{'debug_level'} ) # bad dbg level
1482             )
1483             ) {
1484             # log message is successfully processed, so shift it off
1485 0           shift @{$self->{debug_queue}};
  0            
1486             }
1487             else {
1488 0           $self->debugPush();
1489 0           $self->logLocal("Cannot log message \'$log_message\' to " .
1490             $self->getLogFile() . " = " . $!, 9);
1491 0           $self->invalidateLogFILES();
1492 0           $self->debugPop();
1493             }
1494             }
1495             }
1496             }
1497             else {
1498 0           $self->logLocal("logLocal() called without any parameters!",3);
1499             }
1500              
1501 0           while ($#{$self->{debug_queue}} >= $self->{max_debug_queue_size}) {
  0            
1502             # expire old entries; this needs to happen if $self->{debug_level}
1503             # is undefined or there is no writable log file, otherwise the
1504             # queue could exhaust RAM.
1505 0           shift @{$self->{debug_queue}};
  0            
1506             }
1507             }
1508            
1509              
1510             =item $obj_instance->logError($log_message,$flag);
1511              
1512             The C function takes two arguments, the second one being optional.
1513             The C<$log_message> argument specifies the message to be written to the error
1514             file. If the C<$flag> argument is defined and is non-zero, the C<$log_message>
1515             is also written to STDERR. The C<$log_message> is also passed to C.
1516             A message passed via logError() will always get logged to the log file
1517             regardles of the debug level. Note, a trailing new line, if it exists, is
1518             stripped from the log message.
1519              
1520             =cut
1521              
1522              
1523             sub logError($;$) {
1524            
1525 0     0 1   my $self = shift;
1526 0           my $log_message = shift;
1527 0           my $flag = shift;
1528 0 0         if (defined $log_message) {
1529 0           chomp $log_message;
1530 0           $self->logLocal($log_message, 0);
1531              
1532             #printing error message to STDERR if flag is non zero.
1533 0 0 0       if ( (defined($flag) ) && ($flag ne '0') ) {
1534 0           print STDERR "$log_message\n";
1535             }
1536              
1537 0           $log_message = getLogfileDate() . $log_message;
1538 0           push(@{$self->{error_queue}}, $log_message);
  0            
1539            
1540 0   0       while (
1541             ( defined ( my $log_message = $self->{error_queue}[0]) ) &&
1542             ( defined ( $self->getErrorFile() ) )
1543             ) {
1544 0 0 0       if (
      0        
      0        
1545             ($self->openLogERROR() ) &&
1546             (print ERRLOG "$log_message\n") &&
1547             ($self->closeLogERROR() ) &&
1548             ($self->{error_file_used} = 1) # that is an '='
1549             ) {
1550 0           shift @{$self->{error_queue}};
  0            
1551             }
1552             else {
1553 0           $self->debugPush();
1554 0           $self->logLocal("Cannot log message \'$log_message\' to " .
1555             $self->getErrorFile() . " = $!", 6);
1556 0           $self->invalidateLogFILES();
1557 0           $self->debugPop();
1558             }
1559             }
1560             }
1561             else {
1562 0           $self->logLocal("logError() called without any parameters!",3);
1563             }
1564              
1565 0           while ($#{$self->{error_queue}} >= $self->{max_debug_queue_size}) {
  0            
1566             # expire old entries; this needs to happen if $self->{debug_level}
1567             # is undefined or there is no writable log file, otherwise the
1568             # queue could exhaust RAM.
1569 0           shift @{$self->{error_queue}};
  0            
1570             }
1571             }
1572            
1573              
1574             =item $obj_instance->bail($log_message);
1575              
1576             The C function takes a single required argument. The C<$log_message>
1577             argument specifies the message to be passed to C and written
1578             to standard error. All messages passed to C are written to the
1579             log and error files. The C function calls C to terminate the
1580             program. Optionally, a second positive integer argument can be passed as the
1581             exit code to use. Trailing new lines are stripped from the log message.
1582              
1583             =cut
1584              
1585              
1586             sub bail($;$) {
1587 0     0 1   my $self = shift;
1588 0           my $log_message = shift;
1589 0           my $exit_code = shift;
1590              
1591 0 0 0       if ( ( ! defined $exit_code ) || ( $exit_code !~ /^\d+$/ ) ) {
1592 0           $exit_code = 1;
1593             }
1594 0 0         if (defined $log_message) {
1595 0           chomp $log_message; # strip end new line, if it exists
1596 0           $self->logError($log_message);
1597 0           print STDERR $log_message, "\n";
1598             }
1599 0           exit $exit_code;
1600             }
1601              
1602              
1603             # Functional Class : modified methods
1604              
1605             =item $getopts_error_code = $obj_instance->TIGR_GetOptions(@getopts_arguments);
1606              
1607             This function extends C. It may be used
1608             as C is used. TIGR standard options are handled automatically.
1609             Using this method promotes proper module behavior.
1610              
1611             The following options are defined by this function:
1612              
1613             =over
1614              
1615             =item -appendlog
1616              
1617             Passing '1' to this argument turns on log file appending. Log files are
1618             truncated by default.
1619              
1620             =item -debug
1621              
1622             Set debugging to .
1623              
1624             =item -logfile
1625              
1626             Set the TIGR Foundation log file to . NOTE!!! Log files specified
1627             with relative paths will "track" the program as directories change!!!
1628              
1629             =item -version, -V
1630              
1631             Print version information and exit.
1632              
1633             =item -help, -h
1634              
1635             Print help information and exit.
1636              
1637             =item -depend
1638              
1639             Print dependency information and exit.
1640              
1641             =back
1642              
1643             B cannot be overridden or recorded>.
1644             C default variables, ie. those of the form C<$opt_I>,
1645             are not supported. This function will return 1 on success. This method does
1646             not throw an exception on failure to parse command line parameters - this is
1647             unlike Getopt::Long.
1648              
1649             =cut
1650              
1651              
1652             sub TIGR_GetOptions(@) {
1653 0     0 1   my $self = shift;
1654 0           my @user_options = @_;
1655              
1656 0           my $appendlog_var = undef;
1657 0           my $logfile_var = undef;
1658 0           my $debug_var = undef;
1659 0           my $version_var = undef;
1660 0           my $help_var = undef;
1661 0           my $depend_var = undef;
1662              
1663             # these foundation options support the defaults
1664 0           my @foundation_options = (
1665             "appendlog=i" => \$appendlog_var,
1666             "logfile=s" => \$logfile_var,
1667             "debug=i" => \$debug_var,
1668             "version|V" => \$version_var,
1669             "help|h" => \$help_var,
1670             "depend" => \$depend_var
1671             );
1672              
1673 0           Getopt::Long::Configure('no_ignore_case');
1674 0           my $getopt_code = eval 'GetOptions (@user_options, @foundation_options)';
1675              
1676 0 0 0       if ( (defined $help_var) && ($help_var =~ /^(.*)$/) ) {
1677 0           $self->printHelpInfoAndExit();
1678             }
1679              
1680 0 0 0       if ( (defined $version_var) && ($version_var =~ /^(.*)$/) ) {
1681 0           $self->printVersionInfoAndExit();
1682             }
1683              
1684 0 0 0       if ( (defined $depend_var) && ($depend_var =~ /^(.*)$/) ) {
1685 0           $self->printDependInfoAndExit();
1686             }
1687              
1688 0 0 0       if ( (defined $appendlog_var) && ($appendlog_var =~ /^(.*)$/) ) {
1689 0           $appendlog_var = $1;
1690 0           $self->logAppend($appendlog_var);
1691             }
1692              
1693 0 0 0       if ( (defined $logfile_var) && ($logfile_var =~ /^(.*)$/) ) {
1694 0           $logfile_var = $1;
1695 0           $self->setLogFile($logfile_var);
1696             }
1697              
1698 0 0 0       if ( (defined $debug_var) && ($debug_var =~ /^(.*)$/) ) {
1699 0           $debug_var = $1;
1700 0           $self->setDebugLevel($debug_var);
1701             }
1702              
1703             # remove old log files, if necessary
1704 0           for (
1705             my $file_control_var = 0;
1706 0           $file_control_var <= $#{$self->{log_files}};
1707             $file_control_var++
1708             ) {
1709 0           $self->cleanLogFILES();
1710 0           push(@{$self->{log_files}}, shift @{$self->{log_files}});
  0            
  0            
1711             }
1712 0           return $getopt_code;
1713             }
1714              
1715             DESTROY {
1716 0     0     my $self = shift;
1717 0           $self->{finish_time} = time;
1718 0           my $time_difference = $self->{finish_time} - $self->{start_time};
1719 0           my $num_days = int($time_difference / 86400); # there are 86400 sec/day
1720 0           $time_difference -= $num_days * 86400;
1721 0           my $num_hours = int($time_difference / 3600); # there are 3600 sec/hour
1722 0           $time_difference -= $num_hours * 3600;
1723 0           my $num_min = int($time_difference / 60); # there are 60 sec/hour
1724 0           $time_difference -= $num_min * 60;
1725 0           my $num_sec = $time_difference; # the left overs are seconds
1726 0           my $time_str = sprintf "%03d-%02d:%02d:%02d", $num_days, $num_hours,
1727             $num_min, $num_sec;
1728 0           $self->logLocal("FINISH: " . $self->getProgramInfo('name') .
1729             ", elapsed ".$time_str ,0);
1730             }
1731             }
1732              
1733             =back
1734              
1735             =head1 USAGE
1736              
1737             To use this module, load the C package
1738             via the C function. Then, create a new instance of the
1739             object via the C method, as shown below. If applicable,
1740             C and C log messages are printed when the object
1741             is created and destroyed, respectively. It is advisable to
1742             keep the instance of the object in scope for the whole program
1743             to achieve maximum functionality.
1744              
1745             An example script using this module follows:
1746              
1747             use strict;
1748             use TIGR::Foundation;
1749              
1750             my $tfobject = new TIGR::Foundation;
1751              
1752             MAIN:
1753             {
1754             # The following dependencies are not used in
1755             # this script, but are provided as an example.
1756              
1757             my @DEPEND = ("/usr/bin/tee", "/sbin/stty");
1758              
1759             # The user defined $VERSION variable is usable by Perl.
1760             # The auto defined $REVISION variable stores the RCS/CVS revision
1761             # The user defined $VERSION_STRING reports both.
1762              
1763             my $VERSION = '1.0';
1764             my $REVISION = (qw$Revision: 1.1 $)[-1];
1765             my $VERSION_STRING = "$VERSION (Build $REVISION)";
1766              
1767             my $HELP_INFO = "This is my help\n";
1768              
1769             # All of the necessary information must be passed
1770             # to the foundation object instance, as below.
1771              
1772             $tfobject->addDependInfo(@DEPEND);
1773             $tfobject->setVersionInfo($VERSION_STRING);
1774             $tfobject->setHelpInfo($HELP_INFO);
1775              
1776             my $input_file;
1777             my $output_file;
1778              
1779             $tfobject->TIGR_GetOptions("input=s" => \$input_file,
1780             "output=s" => \$output_file);
1781              
1782             # GetOptions(), and subsequently TIGR_GetOptions(), leaves
1783             # the variables unchanged if no corresponding command line
1784             # arguments are parsed. The passed variables are checked below.
1785              
1786             if (defined $input_file) {
1787              
1788             # The log message is written only if debugging is turned on.
1789             # By default, debugging is off. To turn on debugging, use the
1790             # '-debug DEBUG_LEVEL' option on the command line.
1791             # In this example, '-debug 1' would set debugging to level 1
1792             # and report these log messages.
1793              
1794             $tfobject->logLocal("My input file is $input_file", 1);
1795             }
1796              
1797             print "Hello world", "\n";
1798              
1799             # This case is similar to the previous one above...
1800             if (defined $output_file) {
1801             $tfobject->logLocal("My output file is $output_file.", 1);
1802             }
1803             }
1804              
1805             =cut
1806              
1807             1;