BASIS  version 1.2.3 (revision 2104)
StdAux.pm
00001 ##############################################################################
00002 # @file  StdAux.pm
00003 # @brief Standard auxiliary functions.
00004 #
00005 # @note The StdAux.pm module is automatically created by BASIS from the
00006 #       template file StdAux.pm.in which is part of the BASIS installation.
00007 #
00008 # Copyright (c) 2011 University of Pennsylvania. All rights reserved.<br />
00009 # See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00010 #
00011 # Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00012 #
00013 # @ingroup BasisPerlUtilities
00014 ##############################################################################
00015 
00016 package SBIA::BASIS::StdAux;
00017 
00018 # ============================================================================
00019 # modules
00020 # ============================================================================
00021 
00022 use strict;
00023 use warnings;
00024 
00025 use SBIA::BASIS::ExecutableTargetInfo qw(get_executable_path get_executable_name);
00026 
00027 # ============================================================================
00028 # exports
00029 # ============================================================================
00030 
00031 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
00032 
00033 BEGIN {
00034     use Exporter ();
00035 
00036     $VERSION = 1.02_03;
00037     @ISA     = qw (Exporter);
00038 
00039     %EXPORT_TAGS = (
00040         default => [qw (
00041             print_version
00042             print_contact
00043             execute_process
00044         )],
00045 
00046         everything => [qw (
00047             print_version
00048             print_contact
00049             execute_process
00050         )]
00051     );
00052 
00053     Exporter::export_ok_tags ('everything');
00054 }
00055 
00056 
00057 ## @addtogroup BasisPerlUtilities
00058 # @{
00059 
00060 
00061 # ============================================================================
00062 # version / contact
00063 # ============================================================================
00064 
00065 # ----------------------------------------------------------------------------
00066 ## @brief Print version information including copyright and license notices.
00067 #
00068 # @param [in] name      Name of executable. Should not be set programmatically
00069 #                       to the first argument of the main script.
00070 # @param [in] copyright The copyright notice. If undef, the official default
00071 #                       copyright is used without year, which is not desired.
00072 #                       If an empty string is given, no copyright notice is
00073 #                       printed.
00074 # @param [in] license   Information regarding licensing. If undef, the official
00075 #                       software license of SBIA is used. If an empty string
00076 #                       is given, no license information is printed.
00077 sub print_version
00078 {
00079     my ($name, $copyright, $license) = @_;
00080     # version
00081     die "print_version(): Executable name not specified!\n" unless defined($name);
00082     print $name, " (BASIS) version 1.2.3 (revision 2104)\n";
00083     # copyright notice
00084     if (defined $copyright) {
00085         print $copyright, "\n" unless $copyright == '';
00086     } else {
00087         print "Copyright (c) University of Pennsylvania. All rights reserved.\n";
00088     }
00089     # license information
00090     if (defined $license) {
00091         print $license, "\n" unless $license == '';
00092     } else {
00093         print "See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.\n";
00094     }
00095 }
00096 
00097 # ----------------------------------------------------------------------------
00098 ## @brief Print contact information.
00099 #
00100 # @param [in] contact Name of contact. If undef, the default contact of SBIA
00101 #                     is used, which is recommended.
00102 sub print_contact
00103 {
00104     my $contact = $_[0];
00105     print "Contact:\n  ";
00106     if (defined $contact) {
00107         print $contact
00108     } else {
00109         print "SBIA Group <sbia-software at uphs.upenn.edu>"
00110     }
00111     print "\n";
00112 }
00113 
00114 # ============================================================================
00115 # command execution
00116 # ============================================================================
00117 
00118 # ----------------------------------------------------------------------------
00119 ## @brief Execute command as subprocess.
00120 #
00121 # This command takes either an array reference reference or a string as first
00122 # argument. All other arguments are keyword arguments using hash notation.
00123 #
00124 # Example:
00125 # @code
00126 # # only returns exit code of command but does not output anything
00127 # my $status = execute_process(['ls', '/'], quiet => 1);
00128 # # returns exit code of command and returns command output without
00129 # # printing it to stdout.
00130 # my ($status, $stdout) = execute_process('ls /', quiet => 1, stdout => 1);
00131 # @endcode
00132 #
00133 # @param [in] args       Command with arguments given either as single quoted
00134 #                        string or array of command name and arguments.
00135 #                        In the latter case, the array elements are converted
00136 #                        to strings using the built-in str() function.
00137 #                        Hence, any type which can be converted to a string
00138 #                        can be used.
00139 # @param [in] quiet      Turns off output of stdout of child process to
00140 #                        stdout of parent process.
00141 # @param [in] stdout     Whether to return the command output.
00142 # @param [in] allow_fail If true, does not raise an exception if return
00143 #                        value is non-zero. Otherwise, an exception is
00144 #                        raised by this function using die.
00145 # @param [in] verbose    Verbosity of output messages.
00146 #                        Does not affect verbosity of executed command.
00147 # @param [in] simulate   Whether to simulate command execution only.
00148 #
00149 # @return Exit code of executed command. If @p stdout is true, a tuple
00150 #         consisting of the exit code and command output is returned.
00151 #
00152 # @throws die If command execution failed. This exception is not raised
00153 #             if the command executed with non-zero exit code but
00154 #             @p allow_fail is set to a non-false value.
00155 sub execute_process
00156 {
00157     # arguments
00158     my $args = shift or die "execute_process(): Too few arguments given";
00159     if ($args =~ m/^(quiet|stdout|allow_fail|verbose|simulate)$/) {
00160         warn "execute_process(): First argument matches option name. Missing args argument?";
00161     }
00162     my %defaults = (quiet => 0, stdout => 0, allow_fail => 0, 
00163             verbose => 0, simulate => 0);
00164     my %options = (%defaults, @_);
00165     # get command name and arguments
00166     my $command = '';
00167     my $arguments = '';
00168     # if input is an array
00169     if (ref($args) eq 'ARRAY') {
00170         @$args > 0 or die "execute_process(): No command specified";
00171         $command = shift @$args;
00172         $arguments = '';
00173         for my $arg (@$args) {
00174             if ($arg =~ m/\s/) {
00175                 # escape double quotes
00176                 $arg =~ s/"/\\"/g;
00177                 # quote argument
00178                 $arg = '"' . $arg . '"';
00179             }
00180             $arguments .= ' ';
00181             $arguments .= $arg;
00182         }
00183     # if input is a string
00184     } elsif (ref($args) eq '') {
00185         # extract command from string
00186         $args =~ m/^\s*('([^']|\\')*[^\\]'|"([^"]|\\")*[^\\]"|\S+)(.*)$/;
00187         $command = $1;
00188         $arguments = $4;
00189     # otherwise, wrong input type
00190     } else {
00191         die "execute_process(): Argument args must be either array reference or string";
00192     }
00193     # map build target name to executable file
00194     my $exec_path = get_executable_path($command);
00195     defined $exec_path or die "$command: Either unknown build target or command not found";
00196     # quote executable path if necessary
00197     not $exec_path =~ m/\s/ or $exec_path = '"' . $exec_path . '"';
00198     # prepend absolute path of found executable
00199     $args = $exec_path . $arguments;
00200     # some verbose output
00201     if ($options{'verbose'} gt 0) {
00202         print "\$ ", $args;
00203         $options{'simulate'} and print " (simulated)";
00204         print "\n";
00205     }
00206     # execute command
00207     my $status = 0;
00208     my $output = '';
00209     if (not $options{'simulate'}) {
00210         open CMD, "$args |" or die "$command: Failed to open subprocess";
00211         my $ofh = select STDOUT;
00212         $|++;
00213         while (<CMD>) {
00214             print $_ unless $options{'quiet'};
00215             $output .= $_ if $options{'stdout'};
00216         }
00217         $|--;
00218         select $ofh;
00219         close CMD;
00220         $status = $?;
00221     }
00222     # if command failed, throw an exception
00223     if ($status != 0 and not $options{'allow_fail'}) {
00224         die "Command $args failed";
00225     }
00226     # return
00227     if ($options{'stdout'}) {
00228         return ($status, $output);
00229     } else {
00230         return $status;
00231     }
00232 }
00233 
00234 
00235 ## @}
00236 # end of Doxygen group
00237 
00238 
00239 1; # indicate success of module loading