ParFilename.cc

00001 // --8<--8<--8<--8<--
00002 //
00003 // Copyright (C) 2006 Smithsonian Astrophysical Observatory
00004 //
00005 // This file is part of paramxx
00006 //
00007 // paramxx is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // paramxx is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with this program; if not, write to the 
00019 //       Free Software Foundation, Inc. 
00020 //       51 Franklin Street, Fifth Floor
00021 //       Boston, MA  02110-1301, USA
00022 //
00023 // -->8-->8-->8-->8--
00024 
00025 #include <unistd.h>
00026 #include <fcntl.h>
00027 #include <fstream>
00028 #include <cstdlib>
00029 #include <cstring>
00030 
00031 using namespace std;
00032 
00033 #include <suplibxx/str.h>
00034 
00035 #include "ParFilename.h"
00036 
00037 // The order which the environment variables shall be search for:
00038 static const char* environment_variables[] = { "PDIRS", "PFILES", "UPARM" };
00039 #define NUM_ENV_VAR sizeof(environment_variables)/sizeof(char *)
00040 
00041 // The order which the file extension shall be searched for:
00042 static const char* pfile_extension[] = { ".par" };
00043 #define NUM_EXTENSION sizeof(pfile_extension)/sizeof(char *)
00044 
00045 typedef vector< string > myVector;
00046 typedef myVector::const_iterator myVectorIterator;
00047 
00048 ParFilename::ParFilename( int argc, char** argv, const char* file ) 
00049   throw ( ParFileException ) {
00050 
00051   try {
00052     init_ParFilename( argc, argv, file );
00053   } catch( ParFileException& pfe ) {
00054     throw;
00055   }
00056 
00057 }
00058 
00059 int ParFilename::accessible( const char* str ) throw ( ParFileException ) {
00060 
00061   try {
00062     // if the filename is an empty string 
00063     // then obviously the file is not accessible.
00064     if ( 0 == str || 0 == *str ) 
00065       return EXIT_FAILURE;
00066 
00067     if ( 0 == ::access( str, R_OK ) ) {
00068       if ( '/' == str[ 0 ] ) {
00069         // copy file from wherever to local working directory
00070         // comment out for now, will implement using the correct requirements
00071         // copy_pfile( str );
00072         // Since we no longe copy the file to the current directory
00073         // filename = "./";
00074         // filename += get_basename( str );
00075       }
00076       filename = str;
00077 
00078       return EXIT_SUCCESS;
00079     }
00080 
00081   } catch( ParFileException& pfe ) {
00082 
00083     string msg( "ParFilename::accessible( " );
00084     msg.append( str );
00085     msg.append( " )\n" );
00086     pfe.set_message( msg );
00087     throw pfe;
00088 
00089   }
00090    
00091   return EXIT_FAILURE;
00092 
00093 }
00094 
00095 void ParFilename::check_environment_variables( ) throw ( ParFileException ) {
00096 
00097   // Make sure that at least one of the environment variables is set.
00098   // Keep a counter of the number of environment variables which is not set.
00099   int env_var_counter = 0;
00100   {
00101     for ( size_t i = 0; i < NUM_ENV_VAR; i++ )
00102       if ( NULL == getenv( environment_variables[ i ] ) )
00103         env_var_counter++;
00104   }
00105 
00106   if ( NUM_ENV_VAR == env_var_counter ) {
00107 
00108     // If the number of env_var_counter is equal to the number of environment 
00109     // variables then not a single environment variable is set.
00110     string msg = "ParFilename::check_environment_variables( ) : "
00111       "One of the following environment variables ";
00112     
00113     for ( size_t i = 0; i < NUM_ENV_VAR; i++ ) {
00114       msg.append( "`" );
00115       msg.append( environment_variables[ i ] );
00116       msg.append( "'" );
00117       if ( i != NUM_ENV_VAR - 1 )
00118         msg.append( ", " );
00119     }
00120      
00121     msg.append( " must be defined\n" );
00122 
00123     throw ParFileException( msg );
00124 
00125   }
00126 
00127   return;
00128 
00129 }
00130 
00131 void ParFilename::copy_pfile( const char* str ) 
00132   const throw ( ParFileException ) {
00133 
00134   int f1, f2, n;
00135   char buf[BUFSIZ];
00136 
00137   if ( -1 == (f1 = open( str, O_RDONLY, 0 ) ) ) {
00138     string msg( "ParFilename::copy_pfile( " );
00139     msg.append( str );
00140     msg.append( " ) : Unable to open file for reading\n" );
00141     throw ParFileException( msg );
00142   }
00143 
00144   if ( -1 == (f2 = creat( get_basename( str ), 0644 ) ) ) {
00145     string msg( "ParFilename::copy_pfile( " );
00146     msg.append( str );
00147     msg.append( ", ostream& ) : Unable to open file for writing\n" );
00148     close( f1 );
00149     throw ParFileException( msg );
00150   }
00151 
00152   while( (n = read( f1, buf, BUFSIZ ) ) > 0 )
00153     if ( n != write( f2, buf, n ) ) {
00154       string msg( "ParFilename::copy_pfile( " );
00155       msg.append( str );
00156       msg.append( " ) : Error writing to file" );
00157       close( f1 );
00158       close( f2 );
00159       throw ParFileException( msg );
00160     }
00161 
00162   close( f1 );
00163   close( f2 );
00164 
00165   return;
00166   
00167 }
00168 
00169 int ParFilename::find_pfile( const char* name ) throw ( ParFileException ) {
00170 
00171   try {
00172 
00173     // The absolute pathname was given with the correct extension.
00174     // Make sure that it contains an extention otherwise the library
00175     // may have mistaken the executable for the parfile.
00176     if ( strstr( name, "." ) && EXIT_SUCCESS == accessible( name ) )
00177       return EXIT_SUCCESS;
00178 
00179     for ( size_t ii = 0; ii < NUM_ENV_VAR; ii++ ) {
00180 
00181       char* env_var = getenv( environment_variables[ ii ] );
00182 
00183       if ( env_var ) {
00184 
00185         string directories( env_var );
00186 
00187         vector< string > directory;
00188         suplib::tok( directory, directories, ":;" );
00189 
00190         /*
00191         vector< string > directory =
00192           parse_string( s, pfiles_delimit );
00193         */
00194 
00195         for ( myVectorIterator iter = directory.begin( );
00196               iter != directory.end( ); ++iter ) {
00197 
00198           char fname[ 1024 ];
00199           sprintf( fname, "%s/%s.par", iter->data( ), name );
00200 
00201           if( EXIT_SUCCESS == accessible( fname ) )
00202             return EXIT_SUCCESS;
00203 
00204         }
00205 
00206       }
00207 
00208     }
00209 
00210     return EXIT_FAILURE;
00211 
00212   } catch ( ParFileException& pfe ) {
00213 
00214     throw;
00215 
00216   }
00217 
00218 }
00219 
00220 const char* ParFilename::get_basename( const char* name ) const {
00221 
00222   if ( name || *name ) {
00223 
00224     const char* progname = name;
00225 
00226     char dirdelimit[ 2 ] = { dir_delimit, '\0' };
00227 
00228     const char* ptr = name;
00229 
00230     do {
00231 
00232       ptr = strstr( progname, dirdelimit );
00233       if ( ptr )
00234         progname = ptr + 1;
00235 
00236     } while( ptr );
00237 
00238     return progname;
00239 
00240   } else
00241     return NULL;
00242 
00243 }
00244 
00245 void ParFilename::init_ParFilename( int argc, char** argv,
00246                                     const char* file ) 
00247   throw ( ParFileException ) {
00248 
00249   try {
00250 
00251     check_environment_variables( );
00252 
00253     // loop thru the cmdline arguments.  If PFILE is one of the
00254     // options then check if the requested file is present
00255     for ( int i = 1; i < argc; i++ ) {
00256 
00257       const char* ptr = strstr( argv[ i ], PFILE );
00258       if ( ptr ) {
00259       
00260         ptr += strlen( PFILE );
00261         if ( EXIT_SUCCESS == find_pfile( ptr ) )
00262           return;
00263 
00264       }
00265 
00266     }
00267 
00268     //
00269     // If a specific file was requested then it takes
00270     //  preference over the default file ( using argv[0] ).
00271     //
00272     if ( file ) {
00273       if ( EXIT_SUCCESS == find_pfile( file ) )
00274         return;
00275 
00276       string msg( "ParFilename::init_ParFilename( ) : "
00277                   "Unable to find parfile `" );
00278       msg.append( file );
00279       msg.append( "'\n" );
00280 
00281       throw ParFileException( msg ) ;
00282 
00283     }
00284 
00285     // argv[ 0 ] contains the full pathname.  Therefore,
00286     // one must find the basename of the executable.
00287     const char* progname = get_basename( argv[ 0 ] );
00288 
00289     if ( EXIT_SUCCESS == find_pfile( progname ) )
00290       return;
00291 
00292   } catch ( ParFileException& pfe ) {
00293 
00294     throw pfe;
00295 
00296   }
00297 
00298   string msg( "ParFilename::init_ParFilename( ) : "
00299               "Unable to find parfile for `" );
00300   msg.append( argv[ 0 ] );
00301   msg.append( "'\n" );
00302 
00303   throw ParFileException( msg );
00304 
00305 }
00306 
00315 vector<string> ParFilename::parse_string( string& str, char delimit ) {
00316 
00317   vector<string> tokens;
00318  
00319   if ( str.size( ) ) {
00320 
00321     size_t st0 = 0, st1 = 0;
00322     do {
00323 
00324       st1 = str.find( delimit, st0 );
00325       if ( str.size( ) < st1 ) 
00326         st1 = str.size( );
00327 
00328       tokens.push_back( str.substr( st0, st1 - st0 ) );
00329 
00330       st0 = st1 + 1;
00331 
00332     } while ( str.size( ) > st1 );
00333 
00334   }
00335 
00336   return tokens;
00337 }
00338 
00339 #undef NUM_ENV_VAR
00340 #undef NUM_EXTENSION

Generated on Thu Oct 2 17:54:19 2008 for paramxx by  doxygen 1.5.6