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