Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

cbhey.cc

Go to the documentation of this file.
00001 /*
00002  * cbhey.cc
00003  *
00004  * Copyright (c) 2003 The University of Utah and the Flux Group.
00005  * All rights reserved.
00006  *
00007  * This file is licensed under the terms of the GNU Public License.  
00008  * See the file "license.terms" for restrictions on redistribution 
00009  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  */
00011 
00012 /**
00013  * @file cbhey.cc
00014  *
00015  * Main file for a command line utility used to communicate with active CPU
00016  * broker objects.
00017  */
00018 
00019 #include "config.h"
00020 
00021 #include <errno.h>
00022 #include <stdlib.h>
00023 
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 
00027 #include <assert_pp.h>
00028 #include <factory_library.h>
00029 
00030 #include <corba.h>
00031 
00032 #include <string>
00033 
00034 #include "ltdl.h"
00035 
00036 /* BEGIN HACK */
00037 #define private public
00038 #include "ior-handler.h" // XXX
00039 #undef private
00040 /* END HACK */
00041 
00042 #include "HeyParser.hh"
00043 
00044 using namespace std;
00045 
00046 #if !defined(__XSTRING)
00047 /**
00048  * Convert a macro argument to a string.
00049  *
00050  * @param x The macro to expand to a string.
00051  */
00052 #define __XSTRING(x) __STRING(x)
00053 #endif
00054 
00055 enum {
00056     CDB_DEBUG,
00057     CDB_LIST,
00058 };
00059 
00060 /**
00061  * Flags for the cbhey_data.cd_Flags field.
00062  *
00063  * CDF_LIST - Just list the supported interface/implementation types.
00064  */
00065 enum {
00066     CDF_DEBUG = (1L << CDB_DEBUG),
00067     CDF_LIST = (1L << CDB_LIST),
00068 };
00069 
00070 /**
00071  * Global data for the tool.
00072  *
00073  * cd_Flags - Holds the CDF_ flags.
00074  * cd_InterfaceType - The cast type given on the command line.
00075  */
00076 static struct {
00077     unsigned long cd_Flags;
00078     const char *cd_InterfaceType;
00079 } cbhey_data;
00080 
00081 /**
00082  * Print the usage statement to standard error.
00083  *
00084  * @param prog_name The program name.
00085  */
00086 static void cbhUsage(const char *prog_name)
00087 {
00088     require(prog_name != NULL);
00089 
00090     cerr << "Generic CPU Broker control program.\n"
00091          << "Usage: "
00092          << prog_name
00093          << " [options] <ior> <verb> <specifiers> ...\n"
00094          << endl
00095          << "Options:\n"
00096          << "  -h\t\tThis help message.\n"
00097          << "  -V\t\tShow the version number.\n"
00098 
00099          << "  -d\t\tTurn on debugging messages.\n"
00100          << "  -l\t\tList the supported types.\n"
00101          << "  -c <type>\tCast the object to the given interface.\n"
00102 
00103          << endl
00104         
00105          << "Package: " << PACKAGE_STRING << endl
00106          << "Contact: " << PACKAGE_BUGREPORT << endl
00107 
00108         ;
00109 }
00110 
00111 /**
00112  * Process the command line options.
00113  *
00114  * @param argc_inout Reference to main's argc variable.  On return, the
00115  * variable will contain the number of arguments remaining after option
00116  * processing.
00117  * @param argv_inout Reference to main's argv variable.  On return, the
00118  * variable will contain the remaining argument values.
00119  * @return True if the options were processed correctly, false otherwise.
00120  */
00121 static int cbhProcessOptions(int &argc_inout, char **&argv_inout)
00122 {
00123     int ch, retval = 0;
00124     char *prog_name;
00125     char **argv;
00126     int argc;
00127 
00128     argc = argc_inout;
00129     argv = argv_inout;
00130     prog_name = argv[0];
00131     while( ((ch = getopt(argc, argv, "hVldc:")) != -1) &&
00132            (retval == 0) )
00133     {
00134         switch( ch )
00135         {
00136         case 'c':
00137             cbhey_data.cd_InterfaceType = optarg;
00138             break;
00139         case 'd':
00140             cbhey_data.cd_Flags |= CDF_DEBUG;
00141             break;
00142         case 'l':
00143             cbhey_data.cd_Flags |= CDF_LIST;
00144             break;
00145         case 'V':
00146             cerr << PACKAGE_VERSION << endl;
00147             retval = -1;
00148             break;
00149         case 'h':
00150         case '?':
00151         default:
00152             retval = 1;
00153             break;
00154         }
00155     }
00156     argc_inout -= optind;
00157     argv_inout += optind;
00158 
00159     argc_inout += 1;
00160     argv_inout -= 1;
00161     argv_inout[0] = prog_name;
00162     return( retval );
00163 }
00164 
00165 /* XXX BEGIN Transplanted from TAO */
00166 static void interpret_ior(IorHandler *ioh,
00167                           char *thisIor,
00168                           struct IOR_Manager *thisIorInfo)
00169 {
00170     int numCharsToSkip;
00171     int validTypeId = 0;
00172     int ulongValue;
00173 
00174     // Skip the prefix "IOR:"
00175     int numHexCharsRead = 4;
00176 
00177     // Type ID must be at least 4 bytes in length since type_id is prefixed
00178     // by the string "IDL:"
00179     int validTypeIdLen = 0;
00180 
00181     while (!validTypeIdLen)
00182     {
00183         ioh->skipNullOctets((char *)(thisIor + numHexCharsRead),
00184                             &numCharsToSkip, 1);
00185         numHexCharsRead += numCharsToSkip;
00186 
00187         // Read the length of the type_id field
00188         ulongValue = ioh->getOctet2Field((char *)(thisIor + numHexCharsRead),
00189                                          &numCharsToSkip);
00190 
00191         if (ulongValue == 0)
00192         {
00193             return;
00194         }
00195 
00196         numHexCharsRead += numCharsToSkip;
00197 
00198         if (ulongValue > 4)
00199         {
00200             validTypeIdLen = 1;
00201             thisIorInfo->typeIdLen = ulongValue;
00202         }
00203 
00204         ioh->skipNullOctets((char *)(thisIor + numHexCharsRead),
00205                             &numCharsToSkip, 1);
00206         numHexCharsRead += numCharsToSkip;
00207 
00208         // Read the Type ID
00209         ACE_OS::strncpy (thisIorInfo->typeId,
00210                          ioh->getString((char *)(thisIor + numHexCharsRead),
00211                                         2 * thisIorInfo->typeIdLen),
00212                          thisIorInfo->typeIdLen);
00213 
00214         // Confirm that this is a valid TypeId by looking for the IDL
00215         // interface. Additionally, the IDL interface could be extracted
00216         // and used for other purposes.
00217         ioh->getIdlInterface(thisIorInfo->typeId, &validTypeId);
00218 
00219         if (!validTypeId)
00220         {
00221             validTypeIdLen = 0;
00222             numHexCharsRead -= numCharsToSkip;
00223         }
00224     }
00225 }
00226 /* XXX END Transplanted from TAO */
00227 
00228 /**
00229  * Extract the object type from an IOR.  Currently, this function only handles
00230  * form "IOR:IORs of the ..." and "file://...".
00231  *
00232  * @param ior The IOR to interpret.
00233  * @return A string describing the object type (e.g. "IDL:Foo/Bar:1.0").
00234  */
00235 static const char *type_from_ior(const char *ior)
00236 {
00237     static IorHandler ior_handler; // XXX It crashes if its on the stack (?!)
00238 
00239     const char *retval = NULL;
00240     
00241     require(ior != NULL);
00242 
00243     if( cbhey_data.cd_InterfaceType != NULL )
00244     {
00245         retval = cbhey_data.cd_InterfaceType;
00246     }
00247     else if( strncmp("IOR:", ior, 4) == 0 )
00248     {
00249         interpret_ior(&ior_handler, (char *)ior, &ior_handler.parsedIOR);
00250         retval = ior_handler.parsedIOR.typeId;
00251     }
00252     else if( strncmp("file://", ior, 7) == 0 )
00253     {
00254         int fd;
00255         
00256         if( (fd = open((char  *)&ior[7], O_RDONLY)) >= 0 )
00257         {
00258             char ior_buf[MAX_IOR_LEN];
00259             int len;
00260             
00261             len = read(fd, ior_buf, MAX_IOR_LEN - 1);
00262             ior_buf[len] = '\0';
00263             interpret_ior(&ior_handler, ior_buf, &ior_handler.parsedIOR);
00264             retval = ior_handler.parsedIOR.typeId;
00265             close(fd);
00266         }
00267         else
00268         {
00269             perror("open");
00270         }
00271     }
00272     else
00273     {
00274         errno = EINVAL;
00275     }
00276     return( retval );
00277 }
00278 
00279 /**
00280  * The object type to pass through the directory walking functions.
00281  */
00282 struct scan_payload;
00283 
00284 /**
00285  * Hook used to scan a file found in a directory tree.
00286  *
00287  * @param path The path of the file.
00288  * @param sp The payload passed down from further up the call chain.
00289  * @return Zero if the scanner should stop, otherwise an errno value.
00290  */
00291 static int scan_file(const char *path, struct scan_payload *sp);
00292 
00293 /**
00294  * Scan a path, determine its type, and pass to the appropriate function
00295  * (scan_directory/scan_file).
00296  *
00297  * @param path The path to interrogate.
00298  * @param sp The payload passed down from further up the call chain.
00299  * @return Zero if the scanner should stop, otherwise an errno value.
00300  */
00301 static int scan_path(const char *path, struct scan_payload *sp);
00302 
00303 /**
00304  * Scan a directory and pass its contents to the scan_path.
00305  *
00306  * @param path The directory path to walk.
00307  * @param sp The payload passed down from further up the call chain.
00308  * @return Zero if the scanner should stop, otherwise an errno value.
00309  */
00310 static int scan_directory(const char *path, struct scan_payload *sp);
00311 
00312 /**
00313  * Scan through a colon separate list of paths.
00314  *
00315  * @param path_list A colon separate list of paths to search.
00316  * @param sp The payload passed down from further up the call chain.
00317  * @return Zero if the scanner succeeded, otherwise an errno value.
00318  */
00319 static int scan_path_list(char *path_list, struct scan_payload *sp);
00320 
00321 static int scan_directory(const char *path, struct scan_payload *sp)
00322 {
00323     int retval = EINVAL;
00324     DIR *dir;
00325 
00326     require(path != NULL);
00327     require(sp != NULL);
00328 
00329     if( (dir = opendir(path)) != NULL )
00330     {
00331         struct dirent *de;
00332 
00333         while( (retval != 0) && ((de = readdir(dir)) != NULL) )
00334         {
00335             if( (strcmp(de->d_name, ".") == 0) ||
00336                 (strcmp(de->d_name, "..") == 0) )
00337             {
00338             }
00339             else
00340             {
00341                 string sub_path = path;
00342                 
00343                 sub_path += "/";
00344                 sub_path += de->d_name;
00345                 retval = scan_path(sub_path.c_str(), sp);
00346             }
00347         }
00348         closedir(dir);
00349     }
00350     else
00351     {
00352         retval = errno;
00353     }
00354     return( retval );
00355 }
00356 
00357 static int scan_path(const char *path, struct scan_payload *sp)
00358 {
00359     int retval = EINVAL;
00360     struct stat st;
00361 
00362     require(path != NULL);
00363     require(sp != NULL);
00364 
00365     if( stat(path, &st) == 0 )
00366     {
00367         if( st.st_mode & S_IFDIR )
00368         {
00369             retval = scan_directory(path, sp);
00370         }
00371         else
00372         {
00373             retval = scan_file(path, sp);
00374         }
00375     }
00376     else
00377     {
00378         retval = errno;
00379     }
00380     return( retval );
00381 }
00382 
00383 static int scan_path_list(char *path_list, struct scan_payload *sp)
00384 {
00385     int retval = EINVAL;
00386     char *path;
00387 
00388     require(path_list != NULL);
00389     require(sp != NULL);
00390     
00391     while( (retval != 0) && ((path = strsep(&path_list, ":")) != NULL) )
00392     {
00393         retval = scan_path(path, sp);
00394     }
00395     return( retval );
00396 }
00397 
00398 /*
00399  * The payload to be filled out by scan_file.
00400  *
00401  * sp_hey_server_hint - The FMA_HeyServerHint value to be passed to the factory
00402  *   method.  Set by the caller of scan_path_list.
00403  * sp_handle - The handle on the library that can deal with servers that match
00404  *   the given hint.
00405  * sp_method - Cached reference to the libraries factory method.
00406  */
00407 struct scan_payload {
00408     const char *sp_hey_server_hint;
00409     lt_dlhandle sp_handle;
00410     factory_method_t sp_method;
00411 };
00412 
00413 static int scan_file(const char *path, struct scan_payload *sp)
00414 {
00415     int retval = EINVAL;
00416     lt_dlhandle dlh;
00417 
00418     require(path != NULL);
00419     require(sp != NULL);
00420 
00421     if( (dlh = lt_dlopenext(path)) != NULL )
00422     {
00423         factory_method_t fm;
00424         int rc = EINVAL;
00425 
00426         if( cbhey_data.cd_Flags & CDF_LIST )
00427         {
00428             cerr << "    Library: " << path << endl;
00429         }
00430         if( ((fm = (factory_method_t)
00431               lt_dlsym(dlh, __XSTRING(FACTORY_METHOD_SYMBOL))) != NULL) &&
00432             ((rc = flFactoryMethod(fm, FLO_QUERY,
00433                                    FMA_HeyServerHint, sp->sp_hey_server_hint,
00434                                    FMA_TAG_DONE)) == 0) )
00435         {
00436             sp->sp_handle = dlh;
00437             sp->sp_method = fm;
00438             retval = 0;
00439         }
00440         else
00441         {
00442             if( cbhey_data.cd_Flags & CDF_DEBUG )
00443             {
00444                 cerr << path
00445                      << ": does not support type: "
00446                      << (sp->sp_hey_server_hint == NULL ?
00447                          "" :
00448                          sp->sp_hey_server_hint)
00449                      << endl;
00450             }
00451             lt_dlclose(dlh);
00452             retval = rc;
00453         }
00454     }
00455     else
00456     {
00457         if( cbhey_data.cd_Flags & CDF_DEBUG )
00458         {
00459             cerr << path << ": " << lt_dlerror() << endl;
00460         }
00461         retval = errno;
00462     }
00463     return( retval );
00464 }
00465 
00466 /**
00467  * Scan the directory paths specific to cbhey.
00468  *
00469  * @param sp The payload to pass to the directory scanner.
00470  * @return Zero on success, otherwise an errno value.
00471  */
00472 static int scan_cbhey_paths(struct scan_payload *sp)
00473 {
00474     int retval = ENOENT;
00475     char *path_list;
00476 
00477     require(sp != NULL);
00478 
00479     if( (path_list = getenv("CBHEY_PATH")) != NULL )
00480     {
00481         retval = scan_path_list(path_list, sp);
00482     }
00483     if( retval != 0 )
00484     {
00485         retval = scan_path(__XSTRING(PACKAGE_DIRECTORY) "/lib", sp);
00486     }
00487     return( retval );
00488 }
00489 
00490 int main(int argc, char *argv[])
00491 {
00492     const char *prog_name = argv[0];
00493     int retval = EXIT_FAILURE;
00494 
00495 #if defined(HAVE_ACE)
00496     /* Put a sock in ACE */
00497     // ACE_Log_Msg::instance()->priority_mask(0, ACE_Log_Msg::PROCESS);
00498 #endif
00499     
00500     try
00501     {
00502         CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
00503         int rc;
00504 
00505         rc = cbhProcessOptions(argc, argv);
00506         if( lt_dlinit() != 0 )
00507         {
00508             cerr << "Unable to initialize dynamic libraries\n";
00509         }
00510         else if( rc == 0 )
00511         {
00512             struct scan_payload sp;
00513 
00514             memset(&sp, 0, sizeof(sp));
00515             if( cbhey_data.cd_Flags & CDF_LIST )
00516             {
00517                 cout << "Supported interface/implementation types:" << endl;
00518                 scan_cbhey_paths(&sp);
00519                 retval = EXIT_SUCCESS;
00520             }
00521             else if( argc >= 3 )
00522             {
00523                 HeyParser hp(argc, (const char **)argv);
00524                 CORBA::Object_var obj;
00525                 const char *obj_ior;
00526                 
00527                 obj_ior = hp.who();
00528                 obj = orb->string_to_object(obj_ior);
00529                 if( CORBA::is_nil(obj.in()) )
00530                 {
00531                     cerr << "Null object" << endl;
00532                     retval = 10;
00533                 }
00534                 else if( (sp.sp_hey_server_hint = type_from_ior(obj_ior)) ==
00535                          NULL )
00536                 {
00537                     cerr << "Error: Invalid IOR: " << obj_ior << endl;
00538                 }
00539                 else if( scan_cbhey_paths(&sp) == 0 )
00540                 {
00541                     retval = flFactoryMethod(
00542                         sp.sp_method, FLO_HEY,
00543                         FMA_ORB, orb.in(),
00544                         FMA_HeyServerHint, sp.sp_hey_server_hint,
00545                         FMA_HeyParser, &hp,
00546                         FMA_TAG_DONE);
00547                     lt_dlclose(sp.sp_handle);
00548                 }
00549                 else
00550                 {
00551                     cerr << "Error: Unable to find handler library for "
00552                          << sp.sp_hey_server_hint
00553                          << endl;
00554                 }
00555             }
00556             else
00557             {
00558                 cbhUsage(prog_name);
00559             }
00560         }
00561         else
00562         {
00563             if( rc >= 0 )
00564             {
00565                 cbhUsage(prog_name);
00566             }
00567         }
00568     }
00569     catch(const HeyParserException &he)
00570     {
00571         cerr << "Parse error: " << he << endl;
00572     }
00573     catch(const CORBA::SystemException &e)
00574     {
00575         cerr << "Caught Exception: " << e << endl;
00576     }
00577     catch(...)
00578     {
00579         cerr << "Caught an unhandled exception" << endl;
00580     }
00581 
00582     return( retval );
00583 }

Generated on Mon Dec 1 16:29:06 2003 for CPU Broker by doxygen 1.3.4