1 /***************************************************************************
2                           pluginmanager.cpp  -  description
3                              -------------------
4     begin                : ? 10? 27 2003
5     copyright            : (C) 2003 by Sheldon Lee Wen
6     email                : leewsb@hotmail.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include <lineak/pluginmanager.h>
19 #include <lineak/plugin_definitions.h>
20 #include <lineak/lineak_util_functions.h>
21 #include <lineak/lineak_core_functions.h>
22 #include <lineak/lcommand.h>
23 #include <map>
24 #include <iostream>
25 #include <algorithm>
26 
27 #include <lineak/displayctrl.h>
28 #include <lineak/lkbd.h>
29 #include <lineak/lconfig.h>
30 
31 extern "C" {
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <dirent.h>
36 #include <dlfcn.h>
37 }
38 
39 using namespace lineak_core_functions;
40 extern bool verbose;
41 extern bool very_verbose;
42 extern bool global_enable;
43 
PluginManager()44 PluginManager::PluginManager() {
45 }
~PluginManager()46 PluginManager::~PluginManager(){
47       if (!plugin_map.empty())
48          error("Destructing PluginManager and the plugins have not been unloaded!");
49 }
loadPlugin(const string & plugin)50 bool PluginManager::loadPlugin(const string& plugin) {
51         initialize_display_t initialize_display;
52         initialize_t initialize;
53         cleanup_t cleanup;
54 	identifier_t identifier;
55 	identifier_info *plugin_ident;
56 	directivelist_t directive_list;
57 	macrolist_t macro_list;
58 
59         get_display_t get_display;
60 	//display_show_t show;
61 	//display_volume_t volume;
62 	exec_t exec;
63 
64 	string name;
65 	string type;
66 	string version;
67         string description;
68 
69         void *handle;
70         const char *errmsg;
71         plugin_info plinfo;
72 
73   	if (plugin == "" || plugin == snull) {
74 		msg("No plugin to load!");
75 		return false;
76 	}
77 
78 	msg("Loading plugin: "+plugin);
79 	handle = dlopen(plugin.c_str(),RTLD_NOW);
80          // If we cannot dlopen the plugin return false;
81 	if (handle == NULL) {
82 		cerr << "Failed to load plugin " << plugin << ": " << dlerror() << endl;
83 		dlerror();
84 		//dlclose(handle);
85 		return false;
86 	}
87 	dlerror();
88 	/** Once we have dlopened the plugin. We must we able to get all of the requisite
89 	interfaces, or else we skip the plugin all together. The only non-requisite interface
90 	is the initialize_display interface */
91 
92 	// Attempt to get the plugin identifier. This will prevent us from loading the same plugin more than once.
93 	identifier = (identifier_t)dlsym(handle, "identifier");
94 	if((errmsg = dlerror()) != NULL) {
95 		verror("Didn't find identifier() interface: " + string(errmsg));
96 //		show = NULL;
97 //		volume = NULL;
98                 get_display = NULL;
99 		exec = NULL;
100 		dlerror();
101 		dlclose(handle);
102 		return false;
103 	} else {
104 		plugin_ident = identifier();
105 		name = plugin_ident->identifier;
106 		type = plugin_ident->type;
107 		version = plugin_ident->version;
108                 description = plugin_ident->description;
109                 msg("plugin name:" + name);
110                 msg("plugin type:" + type);
111 		msg("plugin version: " + version);
112 		msg("plugin_ident: " + description);
113 		int Vsize = string(VERSION).size();
114 		//cout << "Comparing: " << VERSION << " to the first " << Vsize << " characters of: " << version.substr(0,Vsize) << endl;
115                 if (VERSION != version.substr(0,Vsize)) {
116 		//if (VERSION != version) {
117 			msg("Warning: Version mismatch. Unloading plugin.");
118                         dlerror();
119                         dlclose(handle);
120                         return false;
121                 }
122 		if (type == "MACRO"  || type == "DISPLAY" && (name != "" && name != snull))  {
123         		// Check to see if that plugin is already registered. If so, skip to the next one.
124 			if (hasPlugin(name)) {
125 				error("Plugin: " + name + " is already registered!");
126 				dlerror();
127 				dlclose(handle);
128 				return false;
129 			}
130 		} else {
131 			error("The plugin identifier is empty or is of the incorrect type. This is an invalid plugin");
132 			dlerror();
133 			dlclose(handle);
134 			return false;
135 		}
136 	}
137 	dlerror();
138 
139 	// Attempt to open the initialize interface. I have elected not to use _init b/c it may be borked
140 	// on certain versions of Linux and across platform.
141 	initialize = (initialize_t)dlsym(handle,"initialize");
142 	if((errmsg = dlerror()) != NULL) {
143 		verror("Didn't find initalize() interface: " + string(errmsg));
144 		initialize = NULL;
145 		dlerror();
146 		dlclose(handle);
147 		return false;
148 	}
149 	dlerror();
150 
151 	// Attempt to resolve the cleanup interface for the plugin.
152 	cleanup = (cleanup_t)dlsym(handle,"cleanup");
153 	if((errmsg = dlerror()) != NULL) {
154 		verror("Didn't find cleanup() interface: " + string(errmsg));
155 		cleanup = NULL;
156 		dlerror();
157 		dlclose(handle);
158 		return false;
159 	}
160 	dlerror();
161 
162 	// Attempt to initialize the osd portion of the plugin.
163 	initialize_display = (initialize_display_t)dlsym(handle,"initialize_display");
164 	if((errmsg = dlerror()) != NULL) {
165 		verror("Didn't find initalize_display() interface: " + string(errmsg));
166 		initialize_display = NULL;
167 	}
168 	dlerror();
169 
170 	/** NON Critical interfaces. IE If we don't find these, then we can still proceed. */
171         /*
172         // Attempt to open the exec interface.
173 	volume = (display_volume_t)dlsym(handle, "volume");
174 	if((errmsg = dlerror()) != NULL) {
175 		error("Didn't find volume interface: "+ string(errmsg));
176 		volume = NULL;
177 		if (type == "DISPLAY") {
178 			error("DISPLAY plugin: " + name + "could not load the volume interface");
179 			dlerror();
180 			dlclose(handle);
181 			return false;
182 		}
183 	}
184 	dlerror(); */
185 
186         get_display = (get_display_t)dlsym(handle, "get_display");
187 	if((errmsg = dlerror()) != NULL) {
188 		verror("Didn't find get_display interface: "+ string(errmsg));
189 		get_display = NULL;
190 		if (type == "DISPLAY") {
191 			error("DISPLAY plugin: " + name + "could not load the volume interface");
192 			dlerror();
193 			dlclose(handle);
194 			return false;
195 		}
196 	}
197 	dlerror();
198         /*
199 	// Attempt to open the show interface.
200 	show = (display_show_t)dlsym(handle, "volume");
201 	if((errmsg = dlerror()) != NULL) {
202 	        error("Didn't find show interface: "+ string(errmsg));
203 		show = NULL;
204 		if (type == "DISPLAY") {
205 			error("DISPLAY plugin: " + name + "could not load the show interface");
206 			dlerror();
207 			dlclose(handle);
208 			return false;
209 		}
210 	}
211 	dlerror(); */
212 	// Attempt to open the exec interface.
213 	exec = (exec_t)dlsym(handle, "exec");
214 	if((errmsg = dlerror()) != NULL) {
215 		verror("Didn't find exec() interface: " + string(errmsg));
216 		exec = NULL;
217 		if (type == "MACRO") {
218 			error("MACRO plugin: " + name + "could not load the exec interface");
219 			dlerror();
220 			dlclose(handle);
221 			return false;
222 		}
223 	}
224 	dlerror();
225 	// Attempt to open the macrolist interface
226 	directive_list = (directivelist_t)dlsym(handle,"directivelist");
227 	if((errmsg = dlerror()) != NULL) {
228 		verror("Didn't find directivelist() interface: " + string(errmsg));
229 		directive_list = NULL;
230 		//dlerror();
231 		//dlclose(handle);
232 		//return false;
233 	}
234 	dlerror();
235 	// Attempt to open the macrolist interface
236 	macro_list = (macrolist_t)dlsym(handle,"macrolist");
237 	if((errmsg = dlerror()) != NULL) {
238 		verror("Didn't find macrolist() interface: " + string(errmsg));
239 		macro_list = NULL;
240 		if (type == "MACRO") {
241 			error("MACRO plugin: " + name + "could not open the macrolist interface. This means we cannot get the list of macros that this plugin supports. Closing plugin.");
242 			dlerror();
243 			dlclose(handle);
244 			return false;
245 		}
246 	}
247 	dlerror();
248 
249 	/** Build the data structure and add it to the plugin_map */
250 	plinfo.filename = plugin;
251 	plinfo.handle = handle;
252 	plinfo.identifier = plugin_ident;
253 	plinfo.initialize = initialize;
254 	plinfo.initialize_display = initialize_display;
255 	plinfo.cleanup = cleanup;
256 	plinfo.directivelist = directive_list;
257 	plinfo.macrolist = macro_list;
258 
259 	//plinfo.volume = volume;
260         plinfo.get_display = get_display;
261 	//plinfo.show = show;
262 	plinfo.exec = exec;
263 
264 	plinfo.directives_defined = false;
265 	plinfo.initialized_display = false;
266 	plinfo.macros_defined = false;
267 	//plinfo.have_display = false;
268 	plinfo.loaded = true;
269 	plinfo.initialized = false;
270 	plinfo.macros.clear();
271 	plinfo.directives.clear();
272         vmsg("Entering plugin: " + name);
273 //	if (verbose) cout << "plinfo ---------" << endl;
274 //	if (verbose) cout << plinfo << endl;
275 	plugin_map[name] = plinfo;
276 
277 	return true;
278 }
loadPlugins(vector<string> myplugins)279 vector<string> PluginManager::loadPlugins(vector<string> myplugins) {
280 	string plugin;
281 	vector<string> loadedplugins;
282         map<string, plugin_info>::size_type size = plugin_map.size();
283         vector<string>::size_type numplugins = myplugins.size();
284 	//bool loadflag = true;
285 
286 	if (myplugins.empty()) {
287 		msg("No plugins to load!!");
288                 return loadedplugins;
289         }
290         // Attempt to load all of the plugins.
291         vector<string>::iterator it =myplugins.begin();
292         for (;it!= myplugins.end(); it++) {
293 		plugin = *it;
294 		if(!loadPlugin(plugin)) {
295 			error("Plugin: " + plugin + " failed to load!");
296 		}
297 		else
298 			loadedplugins.push_back(plugin);
299     	}
300     	if (plugin_map.size() != (size + numplugins)) {
301     		error("Could not load all plugins");
302         return loadedplugins;
303     }
304 
305     return loadedplugins;
306 }
307 /** Unload a plugin */
unloadPlugin(const string & plugin)308 void PluginManager::unloadPlugin(const string& plugin) {
309 	vmsg("unloadPlugin: enter for plugin " + plugin);
310 	void* handle = NULL;
311 	cleanup_t cleanup = NULL;
312 	vmsg("PluginManager: cleaning up plugin " + plugin);
313 	handle = plugin_map[plugin].handle;
314 	cleanup = plugin_map[plugin].cleanup;
315 	if (cleanup != NULL)
316                  cleanup();
317         vmsg("PluginManager: closing plugin " + plugin);
318         if (handle != NULL) {
319                 dlclose(handle);
320         }
321 	msg("PluginManager: unloading plugin " + plugin);
322 	//plugin_map.erase(plugin);
323         vmsg("UnloadPlugin: exit");
324 }
325 /** Unloads all loaded plugins. */
unloadAllPlugins()326 void PluginManager::unloadAllPlugins(){
327         string name = "";
328    	map<string,plugin_info>::iterator it = plugin_map.begin();
329 	int n = plugin_map.size();
330 	if (verbose) cout << "Plugins to unload: " << n << endl;
331         msg("PluginManager is unloading plugins");
332 	//for (int i=0 ;it != plugin_map.end(); it++) {
333 	for (unsigned int i=0 ;i < plugin_map.size(); i++) {
334                 if (very_verbose) cout << "Calling unload for plugin: " << it->first << endl;
335 		unloadPlugin(it->first);
336 		it++;
337 	}
338 	vmsg("PluginManager finished unloading plugins");
339         // Remove all plugin entries in the map.
340 	plugin_map.clear();
341 	msg("PluginManager unloading completed");
342 
343 }
344 /** Initialize a particular plugin */
initializePlugin(const string & plugin_ident,LKbd & imyKbd,LConfig & imyConfig,PluginManager * iplugins)345 bool PluginManager::initializePlugin(const string& plugin_ident, LKbd & imyKbd, LConfig & imyConfig, PluginManager *iplugins) {
346 	/** Check to see that the plugin is loaded */
347 	if(plugin_ident != "" && plugin_ident != snull &&
348 	   (hasPlugin(plugin_ident))) {
349 		if (plugin_map[plugin_ident].loaded == true) {
350 			initialize_t initialize;
351 			msg("Initializing Plugin:" + plugin_ident);
352 			initialize = plugin_map[plugin_ident].initialize;
353 			// Insurance
354 			if (initialize != NULL) {
355 				// Get the initialization information
356 				init_info init;
357 				init.kbd = &imyKbd;
358 				init.config = &imyConfig;
359 				init.plugins = iplugins;
360 				init.verbose = verbose;
361 				init.very_verbose = very_verbose;
362 				init.global_enable = global_enable;
363 				/* #ifdef HAVE_XOSD
364 				init.have_display = true;
365 				#else
366 				init.have_display = false;
367 				#endif */
368 				// Call the plugins initialize interface
369 				if (initialize(init)) {
370 				   plugin_map[plugin_ident].initialized = true;
371 				}
372 				else {
373 				   error("Plugin: " + plugin_ident + " failed to initialize. Removing plugin.");
374 				   unloadPlugin(plugin_ident);
375 				   return true;
376 				}
377 				return true;
378 			}
379 			else {
380 				error("initializePlugin: Could not find interface initialize() for plugin: " + plugin_ident);
381 				return false;
382 			}
383 		}
384 		else {
385 			error("initializePlugin: " + plugin_ident + " has not been loaded");
386 			return false;
387 		}
388 	}
389 	else {
390 		error("initializePlugin: Operating on an empty plugin.");
391 		return false;
392 	}
393 	return true;
394 }
395 /** Call the initialize interface for all plugins that we know about internally. */
initializePlugins(LKbd & imyKbd,LConfig & imyConfig,PluginManager * iplugins)396 bool PluginManager::initializePlugins(LKbd & imyKbd, LConfig & imyConfig,PluginManager *iplugins) {
397         map<string,plugin_info>::iterator it = plugin_map.begin();
398 	bool initflag = true;
399 	/** For all plugins, initialize them. If any does not initialize, return false */
400         for (;it != plugin_map.end(); it++) {
401                 if (!initializePlugin((it->first),imyKbd, imyConfig,iplugins))
402 			initflag = false;
403         }
404     	return initflag;
405 }
406 
initializePluginDisplay(const string & plugin,displayCtrl & imyDisplay)407 bool PluginManager::initializePluginDisplay(const string& plugin, displayCtrl & imyDisplay) {
408 	/** Check to see that the plugin is loaded */
409 	if(plugin != "" && plugin != snull) {
410 		if (plugin_map.find(plugin) == plugin_map.end())
411 			return false;
412 		if (plugin_map[plugin].loaded == true ) {
413 			msg("Initializing OSD for plugin: " + plugin);
414         		initialize_display_t initialize_display;
415 			initialize_display = plugin_map[plugin].initialize_display;
416 	        	if (initialize_display != NULL) {
417         	        	if (!initialize_display(&imyDisplay))
418 					return false;
419 				plugin_map[plugin].initialized_display = true;
420 				return true;
421 			}
422 			else {
423 				msg("initializePluginDisplay: Could not find interface initialize_display() for plugin: " + plugin);
424 				return false;
425 			}
426 		}
427 		else {
428 			error( "initializePluginDisplay: " + plugin + " has not been loaded");
429 			return false;
430 		}
431 	}
432 	else {
433 		error("initializePluginDisplay: Operating on an empty plugin.");
434 		return false;
435 	}
436 	return true;
437 }
438 /** Call the initialize interface for all plugins. */
initializePluginsDisplay(displayCtrl & imyDisplay)439 bool PluginManager::initializePluginsDisplay(displayCtrl & imyDisplay) {
440         map<string,plugin_info>::iterator it = plugin_map.begin();
441 	bool initflag = true;
442         for (;it != plugin_map.end(); it++) {
443 		if (verbose) cout << "InitializePluginsDisplay = " << it->first << endl;
444         	if(!initializePluginDisplay((it->first), imyDisplay))
445 			initflag = false;
446         }
447     	return initflag;
448 }
449 //#endif
450 /** Scan the plugins directory for plugins. */
scanForPlugins(const string & directory)451 vector<string> PluginManager::scanForPlugins(const string& directory){
452 	DIR *dp;
453 	struct dirent *entry;
454 	//struct stat statbuf;
455         vector<string> plugins;
456 	string fullpath = directory + '/';
457 	if ((dp = opendir(directory.c_str())) == NULL) {
458 		error("Cannot open plugin directory: " + directory);
459 		return plugins;
460 	}
461 	//chdir(dir);
462 	while ((entry = readdir(dp)) != NULL) {
463 		char* file = entry->d_name;
464 		struct stat statbuf;
465 		lstat(file, &statbuf);
466 		if (strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0 ) {
467 			continue;
468 		}
469 		//if(S_ISLNK(statbuf.st_mode) || S_ISREG(statbuf.st_mode)) {
470 		if(!S_ISLNK(statbuf.st_mode)) {
471                         // Only pickup .so files.
472                         string sname = fullpath + string(entry->d_name);
473                         //if (sname.find('.so')) {
474                         //   cout << "Plugin! " << sname << endl;
475                         //   plugins.push_back(sname);
476                         // }
477                         if (dlopen(sname.c_str(),RTLD_NOW) != NULL)
478 			   plugins.push_back(sname);
479                 }
480 	}
481 	closedir(dp);
482 	return plugins;
483 }
484 /** Get the list of macros defined per plugin */
defineMacroList(const string & plugin)485 bool PluginManager::defineMacroList(const string& plugin) {
486 	/** Check to see that the plugin is loaded */
487 	if(plugin != "" && plugin != snull) {
488 		plugin_info info = plugin_map[plugin];
489 		if (info.loaded == true ) {
490 			macrolist_t macrolistfn;
491 			macro_info* macinfo;
492 			msg("Defining Macro Lists for Plugin:" + plugin);
493 			macrolistfn = info.macrolist;
494 			// Insurance
495 			if (macrolistfn != NULL) {
496 				string *array;
497 				string tmp;
498 				macinfo = macrolistfn();
499 				if (macinfo == NULL) {
500 					msg("Couldn't get macinfo for plugin: " + plugin);
501 					return false;
502 				}
503 				array = macinfo->macro_list;
504 				// If the plugin defined no macros and is a MACRO plugin, unload it and return false.
505 				// If it is not a MACRO plugin, just return. It is not an error for a non-macro plugin to
506 				// not hanve any macros defined.
507 				if (macinfo->num_macros == 0) {
508 					if (info.identifier->type == "MACRO") {
509 						unloadPlugin(plugin);
510 						return false;
511 					}
512 					return true;
513 				}
514        		                for (int i=0; i < macinfo->num_macros; i++) {
515        			                tmp = array[i];
516 			                // Get the vector of macros for this plugin, and add this macro to the end
517         		                // Add this plugins macros to the list of all supported macros.
518 					msg("Adding macro: " + tmp);
519                                         (plugin_map[plugin].macros).push_back(tmp);
520 					macrolist.push_back(tmp);
521        		                }
522 				plugin_map[plugin].macros_defined = true;
523 				return true;
524 			}
525 			else {
526 				error("Macrolist for plugin: " + plugin + " is empty");
527 				return false;
528 			}
529 		}
530 		else {
531 			error("defineMacroList:" + plugin + " has not been loaded or initialized");
532 			return false;
533 		}
534 	}
535 	else {
536 		error("defineMacroList: Operating on an empty plugin.");
537 		return false;
538 	}
539 	return true;
540 }
541 /** Get the list of macros defined across all plugins. */
defineMacroLists()542 bool PluginManager::defineMacroLists() {
543 	if (!plugin_map.empty()) {
544 		map<string,plugin_info>::iterator it = plugin_map.begin();
545 		/** For each plugin */
546 		bool macroflag = true;
547 		for (;it != plugin_map.end(); it++) {
548 			if (!defineMacroList(string(it->first))) {
549 				macroflag = false;
550 			}
551 		}
552 		return macroflag;
553 	}
554 	return false;
555 }
556 /** Define the directives supported by a plugin */
defineDirectivesList(const string & plugin)557 bool PluginManager::defineDirectivesList(const string& plugin) {
558 	/** Check to see that the plugin is loaded */
559 	if(plugin != "" && plugin != snull) {
560 		plugin_info info = plugin_map[plugin];
561 		if (info.loaded == true ) {
562 			directivelist_t directivelistfn;
563 			directive_info* dirinfo;
564 			msg("Defining Directives Lists for Plugin:" + plugin);
565 			directivelistfn = info.directivelist;
566 			// Insurance
567 			if (directivelistfn != NULL) {
568 //				char **array;
569 //				char **defaults;
570 				ConfigDirectives* directives;
571 				string key, def;
572 				dirinfo = directivelistfn();
573 				if (dirinfo == NULL) {
574 					msg("Couldn't get directives info for plugin: " + plugin);
575 					return false;
576 				}
577 				//array = dirinfo->directive_list;
578 				//defaults = dirinfo->directive_defaults;
579 				directives = dirinfo->directives;
580 
581 				// This should really just unload the plugin and return.
582 				if ((directives->getKeys()).size() == 0) {
583 					//unloadPlugin(plugin);
584 					return true;
585 				}
586 				const vector<string>& keys = directives->getKeys();
587        		                for (vector<string>::const_iterator it = keys.begin(); it != keys.end(); it++) {
588        			                key = *it;
589 					def = directives->getValue(key);
590 			                // Get the vector of macros for this plugin, and add this macro to the end
591         		                // Add this plugins macros to the list of all supported macros.
592 					msg("Adding directive: "+key);
593                                         (plugin_map[plugin].directives).addValue(key, def);
594 					// If the directive has not been defined by any other plugin...
595 					if (!directivelist.isSet(key)) {
596 						directivelist.addValue(key, def);
597 					}
598 					msg("Finished adding directive: "+key);
599        		                }
600 				plugin_map[plugin].directives_defined = true;
601 				return true;
602 			}
603 			else {
604 				error("Directives list for plugin: " + plugin + " is empty");
605 				return false;
606 			}
607 		}
608 		else {
609 			error("defineDirectivesList:" + plugin + " has not been loaded or initialized");
610 			return false;
611 		}
612 	}
613 	else {
614 		error("defineDirectivesList: Operating on an empty plugin.");
615 		return false;
616 	}
617 	return true;
618 }
619 /** Define the directives that are supported across all plugins */
defineDirectivesLists()620 bool PluginManager::defineDirectivesLists() {
621 	if (!plugin_map.empty()) {
622 		map<string,plugin_info>::iterator it = plugin_map.begin();
623 		/** For each plugin */
624 		bool directiveflag = true;
625 		for (;it != plugin_map.end(); it++) {
626 			if (!defineDirectivesList(string(it->first))) {
627 				directiveflag = false;
628 			}
629 		}
630 		return directiveflag;
631 	}
632 	return false;
633 }
634 
635 // Execute a command.
exec(LObject * imyKey,XEvent xev)636 exec_t PluginManager::exec(LObject* imyKey, XEvent xev) {
637          map<string,plugin_info>::iterator it = plugin_map.begin();
638  	 vector<string>::iterator is;
639          vector<string>::iterator siter;
640          exec_t exec;
641 	 //cout << "plugin_manager exec, getting command from the key" << endl;
642 	 LCommand command;
643 
644 	 if (imyKey != NULL) {
645 		if (imyKey->getType() == CODE || imyKey->getType() == SYM)
646 		   command = imyKey->getCommand(xev.xkey.state);
647 		if (imyKey->getType() == BUTTON)
648 		   command = imyKey->getCommand(xev.xbutton.state);
649 	 } else
650             return NULL;
651          //cout << "Looking for macro..." << endl;
652 	 //cout << command << endl;
653          //cout << "plugin_manager global_enable = " << global_enable << endl;
654  	/** Go through the plugin_map and for each plugin, look at their list of supported macros.
655  	    If we find a match, then call that plugins exec */
656 	if (command.isEmpty()) {
657 	   error("The command we want to search the plugin list for is empty!");
658 	   return NULL;
659 	}
660 
661 	for (;it != plugin_map.end(); it++) {
662 	   //cout << "Looking for a plugin to handle this" << endl;
663            /** iter will either point to the end() or the element of the current plugin that
664                contains the macro. */
665            siter = find((it->second).macros.begin(),(it->second).macros.end(),command.getMacroType());
666            if (siter != (it->second).macros.end()) {
667 	      //cout << "Found a plugin: " << *siter << endl;
668               break;
669 	   }
670 
671 	}
672 	//cout << "Attempting to execute for plugin: " << *siter << endl;
673         if ( it != plugin_map.end() ) {
674                 msg( "Plugin: " + string(it->first) + " to execute macro " + command.getMacroType());
675                 exec = (it->second).exec;
676 		if (exec != NULL) {
677 			//cout << "Calling exec\n" << endl;
678                         return (exec);
679                         //cout << " Calling exec(imyKey)" << endl;
680 			//exec(imyKey);
681                         //return true;
682                 }
683 	}
684 	//cout << "returning from plugin_manager exec" << endl;
685         // No plugins could be found.
686         return NULL;
687 }
getDisplay(const LConfig & config)688 displayCtrl* PluginManager::getDisplay(const LConfig &config) {
689     string displayp = config.getValue("Display_plugin");
690     //displayCtrl *rdisplay = NULL;
691 
692     if (displayp == DEFAULT_DISPLAY_PLUGIN)
693        return (NULL);
694     //Search for the plugin that corresponds to "Display_plugin" and call it's get_display function.
695     else if (hasPlugin(displayp)) {
696        plugin_info plinfo = plugin_map[displayp];
697        if (plinfo.filename != "" && plinfo.initialized && plinfo.loaded) {
698           get_display_t get_display = plinfo.get_display;
699           if ( get_display != NULL)
700              return (get_display());
701        }
702     }
703     else
704        msg("Display plugin not found");
705 
706     return (NULL);
707 }
print()708 void PluginManager::print() {
709 	map<string,plugin_info>::iterator it = plugin_map.begin();
710 	for (; it != plugin_map.end(); it++) {
711 		cout << "Plugin " << it->first << " of type " << ((it->second).identifier)->type << endl;
712 	        cout << "  Description: " << ((it->second).identifier)->description << endl;
713 		if ( !(it->second).macros.empty() ) {
714 			vector<string>::iterator mit = (it->second).macros.begin();
715 			for (; mit != (it->second).macros.end(); mit++) {
716                    		cout << "  " << *mit << endl;
717 			}
718 		}
719 	}
720 }
listPlugins()721 void PluginManager::listPlugins() {
722 	msg("Listing Plugins");
723 	map<string,plugin_info>::iterator it = plugin_map.begin();
724 	for (; it != plugin_map.end(); it++) {
725 	   cout << "Plugin " << it->first << " of type " << ((it->second).identifier)->type << endl;
726            cout << "  Description: " << ((it->second).identifier)->description << endl;
727         }
728 	cout << endl;
729 }
hasPlugin(const string & plugin)730 bool PluginManager::hasPlugin(const string &plugin) {
731       if (plugin_map.find(plugin) != plugin_map.end())
732 	  return true;
733       return false;
734 }
735