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

cbhey.cc

Go to the documentation of this file.
00001 /*
00002  * cbhey.cc
00003  *
00004  * Copyright (c) 2003, 2004 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 /**
00167  * Interpret an IOR.
00168  *
00169  * @param ioh The object where the interpretation should be stored.
00170  * @param thisIor The IOR to interpret.
00171  * @param thisIorInfo ...
00172  */
00173 static void interpret_ior(IorHandler *ioh,
00174                           char *thisIor,
00175                           struct IOR_Manager *thisIorInfo)
00176 {
00177     int numCharsToSkip;
00178     int validTypeId = 0;
00179     int ulongValue;
00180 
00181     // Skip the prefix "IOR:"
00182     int numHexCharsRead = 4;
00183 
00184     // Type ID must be at least 4 bytes in length since type_id is prefixed
00185     // by the string "IDL:"
00186     int validTypeIdLen = 0;
00187 
00188     while (!validTypeIdLen)
00189     {
00190         ioh->skipNullOctets((char *)(thisIor + numHexCharsRead),
00191                             &numCharsToSkip, 1);
00192         numHexCharsRead += numCharsToSkip;
00193 
00194         // Read the length of the type_id field
00195         ulongValue = ioh->getOctet2Field((char *)(thisIor + numHexCharsRead),
00196                                          &numCharsToSkip);
00197 
00198         if (ulongValue == 0)
00199         {
00200             return;
00201         }
00202 
00203         numHexCharsRead += numCharsToSkip;
00204 
00205         if (ulongValue > 4)
00206         {
00207             validTypeIdLen = 1;
00208             thisIorInfo->typeIdLen = ulongValue;
00209         }
00210 
00211         ioh->skipNullOctets((char *)(thisIor + numHexCharsRead),
00212                             &numCharsToSkip, 1);
00213         numHexCharsRead += numCharsToSkip;
00214 
00215         // Read the Type ID
00216         ACE_OS::strncpy (thisIorInfo->typeId,
00217                          ioh->getString((char *)(thisIor + numHexCharsRead),
00218                                         2 * thisIorInfo->typeIdLen),
00219                          thisIorInfo->typeIdLen);
00220 
00221         // Confirm that this is a valid TypeId by looking for the IDL
00222         // interface. Additionally, the IDL interface could be extracted
00223         // and used for other purposes.
00224         ioh->getIdlInterface(thisIorInfo->typeId, &validTypeId);
00225 
00226         if (!validTypeId)
00227         {
00228             validTypeIdLen = 0;
00229             numHexCharsRead -= numCharsToSkip;
00230         }
00231     }
00232 }
00233 /* XXX END Transplanted from TAO */
00234 
00235 /**
00236  * Extract the object type from an IOR.  Currently, this function only handles
00237  * form "IOR:IORs of the ..." and "file://...".
00238  *
00239  * @param ior The IOR to interpret.
00240  * @return A string describing the object type (e.g. "IDL:Foo/Bar:1.0").
00241  */
00242 static const char *type_from_ior(const char *ior)
00243 {
00244     static IorHandler ior_handler; // XXX It crashes if its on the stack (?!)
00245 
00246     const char *retval = NULL;
00247     
00248     require(ior != NULL);
00249 
00250     if( cbhey_data.cd_InterfaceType != NULL )
00251     {
00252         retval = cbhey_data.cd_InterfaceType;
00253     }
00254     else if( strncmp("IOR:", ior, 4) == 0 )
00255     {
00256         interpret_ior(&ior_handler, (char *)ior, &ior_handler.parsedIOR);
00257         retval = ior_handler.parsedIOR.typeId;
00258     }
00259     else if( strncmp("file://", ior, 7) == 0 )
00260     {
00261         int fd;
00262         
00263         if( (fd = open((char  *)&ior[7], O_RDONLY)) >= 0 )
00264         {
00265             char ior_buf[MAX_IOR_LEN];
00266             int len;
00267             
00268             len = read(fd, ior_buf, MAX_IOR_LEN - 1);
00269             ior_buf[len] = '\0';
00270             interpret_ior(&ior_handler, ior_buf, &ior_handler.parsedIOR);
00271             retval = ior_handler.parsedIOR.typeId;
00272             close(fd);
00273         }
00274         else
00275         {
00276             perror("open");
00277         }
00278     }
00279     else
00280     {
00281         errno = EINVAL;
00282     }
00283     return( retval );
00284 }
00285 
00286 /**
00287  * The object type to pass through the directory walking functions.
00288  */
00289 struct scan_payload;
00290 
00291 /**
00292  * Hook used to scan a file found in a directory tree.
00293  *
00294  * @param path The path of the file.
00295  * @param sp The payload passed down from further up the call chain.
00296  * @return Zero if the scanner should stop, otherwise an errno value.
00297  */
00298 static int scan_file(const char *path, struct scan_payload *sp);
00299 
00300 /**
00301  * Scan a path, determine its type, and pass to the appropriate function
00302  * (scan_directory/scan_file).
00303  *
00304  * @param path The path to interrogate.
00305  * @param sp The payload passed down from further up the call chain.
00306  * @return Zero if the scanner should stop, otherwise an errno value.
00307  */
00308 static int scan_path(const char *path, struct scan_payload *sp);
00309 
00310 /**
00311  * Scan a directory and pass its contents to the scan_path.
00312  *
00313  * @param path The directory path to walk.
00314  * @param sp The payload passed down from further up the call chain.
00315  * @return Zero if the scanner should stop, otherwise an errno value.
00316  */
00317 static int scan_directory(const char *path, struct scan_payload *sp);
00318 
00319 /**
00320  * Scan through a colon separate list of paths.
00321  *
00322  * @param path_list A colon separate list of paths to search.
00323  * @param sp The payload passed down from further up the call chain.
00324  * @return Zero if the scanner succeeded, otherwise an errno value.
00325  */
00326 static int scan_path_list(char *path_list, struct scan_payload *sp);
00327 
00328 static int scan_directory(const char *path, struct scan_payload *sp)
00329 {
00330     int retval = EINVAL;
00331     DIR *dir;
00332 
00333     require(path != NULL);
00334     require(sp != NULL);
00335 
00336     if( (dir = opendir(path)) != NULL )
00337     {
00338         struct dirent *de;
00339 
00340         while( (retval != 0) && ((de = readdir(dir)) != NULL) )
00341         {
00342             if( (strcmp(de->d_name, ".") == 0) ||
00343                 (strcmp(de->d_name, "..") == 0) )
00344             {
00345             }
00346             else
00347             {
00348                 string sub_path = path;
00349                 
00350                 sub_path += "/";
00351                 sub_path += de->d_name;
00352                 retval = scan_path(sub_path.c_str(), sp);
00353             }
00354         }
00355         closedir(dir);
00356     }
00357     else
00358     {
00359         retval = errno;
00360     }
00361     return( retval );
00362 }
00363 
00364 static int scan_path(const char *path, struct scan_payload *sp)
00365 {
00366     int retval = EINVAL;
00367     struct stat st;
00368 
00369     require(path != NULL);
00370     require(sp != NULL);
00371 
00372     if( stat(path, &st) == 0 )
00373     {
00374         if( st.st_mode & S_IFDIR )
00375         {
00376             retval = scan_directory(path, sp);
00377         }
00378         else
00379         {
00380             retval = scan_file(path, sp);
00381         }
00382     }
00383     else
00384     {
00385         retval = errno;
00386     }
00387     return( retval );
00388 }
00389 
00390 static int scan_path_list(char *path_list, struct scan_payload *sp)
00391 {
00392     int retval = EINVAL;
00393     char *path;
00394 
00395     require(path_list != NULL);
00396     require(sp != NULL);
00397     
00398     while( (retval != 0) && ((path = strsep(&path_list, ":")) != NULL) )
00399     {
00400         retval = scan_path(path, sp);
00401     }
00402     return( retval );
00403 }
00404 
00405 /*
00406  * The payload to be filled out by scan_file.
00407  *
00408  * sp_hey_server_hint - The FMA_HeyServerHint value to be passed to the factory
00409  *   method.  Set by the caller of scan_path_list.
00410  * sp_handle - The handle on the library that can deal with servers that match
00411  *   the given hint.
00412  * sp_method - Cached reference to the libraries factory method.
00413  */
00414 struct scan_payload {
00415     const char *sp_hey_server_hint;
00416     lt_dlhandle sp_handle;
00417     factory_method_t sp_method;
00418 };
00419 
00420 static int scan_file(const char *path, struct scan_payload *sp)
00421 {
00422     int retval = EINVAL;
00423     lt_dlhandle dlh;
00424 
00425     require(path != NULL);
00426     require(sp != NULL);
00427 
00428     if( (dlh = lt_dlopenext(path)) != NULL )
00429     {
00430         factory_method_t fm;
00431         int rc = EINVAL;
00432 
00433         if( cbhey_data.cd_Flags & CDF_LIST )
00434         {
00435             cerr << "    Library: " << path << endl;
00436         }
00437         if( ((fm = (factory_method_t)
00438               lt_dlsym(dlh, __XSTRING(FACTORY_METHOD_SYMBOL))) != NULL) &&
00439             ((rc = flFactoryMethod(fm, FLO_QUERY,
00440                                    FMA_HeyServerHint, sp->sp_hey_server_hint,
00441                                    FMA_TAG_DONE)) == 0) )
00442         {
00443             sp->sp_handle = dlh;
00444             sp->sp_method = fm;
00445             retval = 0;
00446         }
00447         else
00448         {
00449             if( cbhey_data.cd_Flags & CDF_DEBUG )
00450             {
00451                 cerr << path
00452                      << ": does not support type: "
00453                      << (sp->sp_hey_server_hint == NULL ?
00454                          "" :
00455                          sp->sp_hey_server_hint)
00456                      << endl;
00457             }
00458             lt_dlclose(dlh);
00459             retval = rc;
00460         }
00461     }
00462     else
00463     {
00464         if( cbhey_data.cd_Flags & CDF_DEBUG )
00465         {
00466             cerr << path << ": " << lt_dlerror() << endl;
00467         }
00468         retval = errno;
00469     }
00470     return( retval );
00471 }
00472 
00473 /**
00474  * Scan the directory paths specific to cbhey.
00475  *
00476  * @param sp The payload to pass to the directory scanner.
00477  * @return Zero on success, otherwise an errno value.
00478  */
00479 static int scan_cbhey_paths(struct scan_payload *sp)
00480 {
00481     int retval = ENOENT;
00482     char *path_list;
00483 
00484     require(sp != NULL);
00485 
00486     if( (path_list = getenv("CBHEY_PATH")) != NULL )
00487     {
00488         retval = scan_path_list(path_list, sp);
00489     }
00490     if( retval != 0 )
00491     {
00492         retval = scan_path(__XSTRING(PACKAGE_DIRECTORY) "/lib", sp);
00493     }
00494     return( retval );
00495 }
00496 
00497 int main(int argc, char *argv[])
00498 {
00499     const char *prog_name = argv[0];
00500     int retval = EXIT_FAILURE;
00501 
00502 #if defined(HAVE_ACE)
00503     ACE_Log_Msg::instance()->priority_mask(0, ACE_Log_Msg::PROCESS);
00504 #endif
00505     
00506     try
00507     {
00508         CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
00509         int rc;
00510 
00511         rc = cbhProcessOptions(argc, argv);
00512         if( lt_dlinit() != 0 )
00513         {
00514             cerr << "Unable to initialize dynamic libraries\n";
00515         }
00516         else if( rc == 0 )
00517         {
00518             struct scan_payload sp;
00519 
00520             memset(&sp, 0, sizeof(sp));
00521             if( cbhey_data.cd_Flags & CDF_LIST )
00522             {
00523                 cout << "Supported interface/implementation types:" << endl;
00524                 scan_cbhey_paths(&sp);
00525                 retval = EXIT_SUCCESS;
00526             }
00527             else if( argc >= 3 )
00528             {
00529                 HeyParser hp(argc, (const char **)argv);
00530                 CORBA::Object_var obj;
00531                 const char *obj_ior;
00532                 
00533                 obj_ior = hp.who();
00534                 obj = orb->string_to_object(obj_ior);
00535                 if( CORBA::is_nil(obj.in()) )
00536                 {
00537                     cerr << "Null object" << endl;
00538                     retval = 10;
00539                 }
00540                 else if( (sp.sp_hey_server_hint = type_from_ior(obj_ior)) ==
00541                          NULL )
00542                 {
00543                     cerr << "Error: Invalid IOR: " << obj_ior << endl;
00544                 }
00545                 else if( scan_cbhey_paths(&sp) == 0 )
00546                 {
00547                     retval = flFactoryMethod(
00548                         sp.sp_method, FLO_HEY,
00549                         FMA_ORB, orb.in(),
00550                         FMA_HeyServerHint, sp.sp_hey_server_hint,
00551                         FMA_HeyParser, &hp,
00552                         FMA_TAG_DONE);
00553                     lt_dlclose(sp.sp_handle);
00554                 }
00555                 else
00556                 {
00557                     cerr << "Error: Unable to find handler library for "
00558                          << sp.sp_hey_server_hint
00559                          << endl;
00560                 }
00561             }
00562             else
00563             {
00564                 cbhUsage(prog_name);
00565             }
00566         }
00567         else
00568         {
00569             if( rc >= 0 )
00570             {
00571                 cbhUsage(prog_name);
00572             }
00573         }
00574     }
00575     catch(const HeyParserException &he)
00576     {
00577         cerr << "Parse error: " << he << endl;
00578     }
00579     catch(const CORBA::SystemException &e)
00580     {
00581         cerr << "Caught Exception: " << e << endl;
00582     }
00583     catch(...)
00584     {
00585         cerr << "Caught an unhandled exception" << endl;
00586     }
00587 
00588     return( retval );
00589 }

Generated on Tue Jun 22 14:50:08 2004 for CPU Broker by doxygen 1.3.6