Listing 4. Source for Main Program Invoking Dynamically Loaded Classes Circle and Square

#include <iostream>
#include <map>
#include <list>
#include <vector>
#include <string>
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
#include "shape.hh"
// size of buffer for reading in directory entries
static unsigned int BUF_SIZE = 1024;
// our global factory for making shapes
map<string, maker_t *, less<string> > factory;
int main(int argc, char **argv){
   FILE *dl;   // handle to read directory
   char *command_str = "ls *.so";  // command
               // string to get dynamic lib names
   char in_buf[BUF_SIZE]; // input buffer for lib
                          // names
   list<void *> dl_list; // list to hold handles
                               // for dynamic libs
   list<void *>::iterator itr;
vector<string> shape_names;  // vector of shape
               // types used to build menu
   list<shape *> shape_list;  // list of shape
               // objects we create
   list<shape *>::iterator sitr;
map<string, maker_t *, less<string> >::iterator fitr;
   // get the names of all the dynamic libs (.so
              // files) in the current dir
   dl = popen(command_str, "r");
   if(!dl){
      perror("popen");
      exit(-1);
   }
   void *dlib;
   char name[1024]; i
   while(fgets(in_buf, BUF_SIZE, dl)){
      // trim off the whitespace
      char *ws = strpbrk(in_buf, " \t\n");
      if(ws) *ws = '\0';
      // append ./ to the front of the lib name
      sprintf(name, "./%s", in_buf);
      dlib = dlopen(name, RTLD_NOW);
      if(dlib == NULL){
         cerr << dlerror() << endl;
         exit(-1);
      }
      // add the handle to our list
      dl_list.insert(dl_list.end(), dlib);
   }
   int i = 0;
   // create an array of the shape names
   for(fitr=factory.begin(); fitr!=factory.end();
        fitr++){
      shape_names.insert(shape_names.end(),
        fitr->first);
      i++;
   }
   int choice;<\n>
   // create a menu of possible shapes to create and let the user make some
   while(1){
      i = 1;
      for(fitr=factory.begin();
           fitr!=factory.end(); fitr++){
         cout << i << " - Create " << fitr->first
            << endl;
         i++;
      }
      cout << i << " - Draw created shapes\n";
      i++; i
      cout << i << " - Exit\n";
      cout << "> ";
      cin >> choice;
      if(choice == i){
         // destroy any shapes we created
         for(sitr=shape_list.begin();
              sitr!=shape_list.end();sitr++){
            delete *sitr;
         }
         // close all the dynamic libs we opened
         for(itr=dl_list.begin(); itr!=dl_list.end(); itr++){
            dlclose(*itr);
         }
         exit(1);
      }
      if(choice == i - 1){
         // draw the shapes
         for(sitr=shape_list.begin();
              sitr!=shape_list.end();sitr++){
            (*sitr)->draw();
         }
      }
      if(choice > 0 && choice < i - 1){
         // add the appropriate shape to the shape list
         shape_list.insert(shape_list.end(),
            factory[shape_names[choice-1]]());
      }
   }
}