1 /*
2  * gsat - a realtime satellite tracking graphical frontend to predict
3  *
4  * Copyright (C) 2001 by Xavier Crehueras, EB3CZS
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * Look at the README for more information on the program.
21  */
22 
23 /* Plugin functions */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <dlfcn.h>
31 #include <dirent.h>
32 #include <gtk/gtk.h>
33 
34 #include "support.h"
35 #include "comms.h"
36 
37 #include "globals.h"
38 
close_uplink_plugin(void)39 void close_uplink_plugin( void )
40 {
41   if(uppluginenable==FALSE)
42     return;
43 
44   /* close rig if it was open before closing plugin */
45   if( enableupdoppler==TRUE ) {
46     (*plugin_close_rig_uplink)();
47     enableupdoppler=FALSE;
48   }
49 
50   dlclose(upplugin_handle);
51 
52   uppluginenable=FALSE;
53 }
54 
open_uplink_plugin(char * plugin)55 int open_uplink_plugin( char * plugin )
56 {
57   char * error;
58 
59   /* if it's already open, close it first */
60   if( uppluginenable==TRUE )
61     close_uplink_plugin();
62 
63   upplugin_handle=dlopen( plugin, RTLD_NOW );
64   if( upplugin_handle==NULL )
65     if( (error=dlerror()) != NULL ) {
66       fprintf(stderr,"Error opening uplink plugin: %s\n",error);
67       return FALSE;
68     }
69 
70   plugin_info_uplink=dlsym(upplugin_handle,"plugin_info");
71   if( plugin_info_uplink==NULL )
72     if( (error=dlerror()) != NULL ) {
73       fprintf(stderr,"Error: plugin_info_uplink: %s\n",error);
74       return FALSE;
75     }
76 
77   plugin_open_rig_uplink=dlsym(upplugin_handle,"plugin_open_rig");
78   if( plugin_open_rig_uplink==NULL )
79     if( (error=dlerror()) != NULL ) {
80       fprintf(stderr,"Error: plugin_open_rig_uplink: %s\n",error);
81       return FALSE;
82     }
83 
84   plugin_close_rig_uplink=dlsym(upplugin_handle,"plugin_close_rig");
85   if( plugin_close_rig_uplink==NULL )
86     if( (error=dlerror()) != NULL ) {
87       fprintf(stderr,"Error: plugin_close_rig_uplink: %s\n",error);
88       return FALSE;
89     }
90 
91   plugin_set_uplink_frequency=dlsym(upplugin_handle,"plugin_set_uplink_frequency");
92   if( plugin_set_uplink_frequency==NULL )
93     if( (error=dlerror()) != NULL ) {
94       fprintf(stderr,"Error: plugin_set_uplink_frequency: %s\n",error);
95       return FALSE;
96     }
97 
98   uppluginenable=TRUE;
99 
100   return TRUE;
101 }
102 
close_downlink_plugin(void)103 void close_downlink_plugin( void )
104 {
105   if(downpluginenable==FALSE)
106     return;
107 
108   /* close rig if it was open before closing plugin */
109   if( enabledowndoppler==TRUE ) {
110     (*plugin_close_rig_downlink)();
111     enabledowndoppler=FALSE;
112   }
113 
114   dlclose(downplugin_handle);
115 
116   downpluginenable=FALSE;
117 }
118 
open_downlink_plugin(char * plugin)119 int open_downlink_plugin( char * plugin )
120 {
121   char * error;
122 
123   /* if it's already open, close it first */
124   if( downpluginenable==TRUE )
125     close_downlink_plugin();
126 
127   downplugin_handle=dlopen( plugin, RTLD_NOW );
128   if( downplugin_handle==NULL )
129     if( (error=dlerror()) != NULL ) {
130       fprintf(stderr,"Error opening downlink plugin: %s\n",error);
131       return FALSE;
132     }
133 
134   plugin_info_downlink=dlsym(downplugin_handle,"plugin_info");
135   if( plugin_info_downlink==NULL )
136     if( (error=dlerror()) != NULL ) {
137       fprintf(stderr,"Error: plugin_info_downlink: %s\n",error);
138       return FALSE;
139     }
140   plugin_open_rig_downlink=dlsym(downplugin_handle,"plugin_open_rig");
141   if( plugin_open_rig_downlink==NULL )
142     if( (error=dlerror()) != NULL ) {
143       fprintf(stderr,"Error: plugin_open_rig_downlink: %s\n",error);
144       return FALSE;
145     }
146   plugin_close_rig_downlink=dlsym(downplugin_handle,"plugin_close_rig");
147   if( plugin_close_rig_downlink==NULL )
148     if( (error=dlerror()) != NULL ) {
149       fprintf(stderr,"Error: plugin_close_rig_downlink: %s\n",error);
150       return FALSE;
151     }
152   plugin_set_downlink_frequency=dlsym(downplugin_handle,"plugin_set_downlink_frequency");
153   if( plugin_set_downlink_frequency==NULL )
154     if( (error=dlerror()) != NULL ) {
155       fprintf(stderr,"Error: plugin_set_downlink_frequency: %s\n",error);
156       return FALSE;
157     }
158 
159   downpluginenable=TRUE;
160 
161   return TRUE;
162 }
163 
close_beacon_plugin(void)164 void close_beacon_plugin( void )
165 {
166   if(beaconpluginenable==FALSE)
167     return;
168 
169   /* close rig if it was open before closing plugin */
170   if( enablebeacondoppler==TRUE ) {
171     (*plugin_close_rig_beacon)();
172     enablebeacondoppler=FALSE;
173   }
174 
175   dlclose(beaconplugin_handle);
176 
177   beaconpluginenable=FALSE;
178 }
179 
open_beacon_plugin(char * plugin)180 int open_beacon_plugin( char * plugin )
181 {
182   char * error;
183 
184   /* if it's already open, close it first */
185   if( beaconpluginenable==TRUE )
186     close_beacon_plugin();
187 
188   beaconplugin_handle=dlopen( plugin, RTLD_NOW );
189   if( beaconplugin_handle==NULL )
190     if( (error=dlerror()) != NULL ) {
191       fprintf(stderr,"Error opening beacon plugin: %s\n",error);
192       return FALSE;
193     }
194 
195   plugin_info_beacon=dlsym(beaconplugin_handle,"plugin_info");
196   if( plugin_info_beacon==NULL )
197     if( (error=dlerror()) != NULL ) {
198       fprintf(stderr,"Error: plugin_info_beacon: %s\n",error);
199       return FALSE;
200     }
201   plugin_open_rig_beacon=dlsym(beaconplugin_handle,"plugin_open_rig");
202   if( plugin_open_rig_beacon==NULL )
203     if( (error=dlerror()) != NULL ) {
204       fprintf(stderr,"Error: plugin_open_rig_beacon: %s\n",error);
205       return FALSE;
206     }
207   plugin_close_rig_beacon=dlsym(beaconplugin_handle,"plugin_close_rig");
208   if( plugin_close_rig_beacon==NULL )
209     if( (error=dlerror()) != NULL ) {
210       fprintf(stderr,"Error: plugin_close_rig_beacon: %s\n",error);
211       return FALSE;
212     }
213   plugin_set_beacon_frequency=dlsym(beaconplugin_handle,"plugin_set_downlink_frequency");
214   if( plugin_set_beacon_frequency==NULL )
215     if( (error=dlerror()) != NULL ) {
216       fprintf(stderr,"Error: plugin_set_beacon_frequency: %s\n",error);
217       return FALSE;
218     }
219 
220   beaconpluginenable=TRUE;
221 
222   return TRUE;
223 }
224 
check_radio_plugin_file(const struct dirent * plugdir)225 int check_radio_plugin_file( const struct dirent * plugdir )
226 {
227   return ! strncmp(plugdir->d_name,"radio_",6);
228 }
229 
search_radio_plugins(void)230 void search_radio_plugins( void )
231 {
232   struct dirent **namelist;
233   int n, i;
234   GtkWidget * widget;
235   char filename[256];
236   DIR * dir;
237 
238   /* empty plugin list if it was created */
239   n = g_list_length(pluginlist);
240   if( n > 0 ) {
241     pluginlist=g_list_first( pluginlist );
242     for( i=0; i<n; i++ )
243       pluginlist=g_list_remove( pluginlist, pluginlist->data );
244     for( i=0; i<n; i++ ) {
245       pluginfiles[i][0]='\0';
246       plugindescriptions[i][0]='\0';
247     }
248   }
249 
250   strcpy( pluginfiles[0], "None");
251   strcpy( plugindescriptions[0], "No Plugin");
252   pluginlist=g_list_append( pluginlist, plugindescriptions[0] );
253 
254   /* check plugin directory */
255   if( (dir=opendir( pluginsdir ))==NULL ) {
256     switch( errno ) {
257     case EACCES:
258       fprintf(stderr, "Error: You don't have access to plugin directory.\n");
259       error_dialog("You don't have access to plugin directory.");
260       break;
261     case ENOENT:
262       fprintf(stderr, "Error: Plugin directory doesn't exist.\n");
263       error_dialog("Plugin directory doesn't exist.");
264       break;
265     case ENOTDIR:
266       fprintf(stderr, "Error: Plugin directory is not a directory.\n");
267       error_dialog("Can't open plugin directory.");
268       break;
269     default:
270       fprintf(stderr, "Error: Can't open plugin directory.\n");
271       error_dialog("Can't open plugin directory.");
272       break;
273     }
274     /* Attach plugin list */
275     widget=lookup_widget( dialog_preferences, "combo_upplugin" );
276     gtk_combo_set_popdown_strings( GTK_COMBO(widget), pluginlist);
277     widget=lookup_widget( dialog_preferences, "combo_downplugin" );
278     gtk_combo_set_popdown_strings( GTK_COMBO(widget), pluginlist);
279     widget=lookup_widget( dialog_preferences, "combo_beaconplugin" );
280     gtk_combo_set_popdown_strings( GTK_COMBO(widget), pluginlist);
281     return;
282   }
283   closedir( dir );
284 
285   /* scan plugin directory and create plugin list */
286   n = scandir(pluginsdir, &namelist, check_radio_plugin_file, alphasort);
287   if (n < 0) {
288     perror("scandir");
289     return;
290   }
291 
292   for( i=0; i<n; i++ ) {
293     strcpy(filename, pluginsdir);
294     strcat(filename, namelist[i]->d_name);
295     if(open_downlink_plugin(filename)==TRUE) {
296       strncpy( pluginfiles[i+1], namelist[i]->d_name, 29);
297       strncpy( plugindescriptions[i+1], (*plugin_info_downlink)(), 29);
298       pluginlist=g_list_append( pluginlist, plugindescriptions[i+1] );
299       close_downlink_plugin();
300     }
301   }
302 
303   /* Attach plugin list */
304   widget=lookup_widget( dialog_preferences, "combo_upplugin" );
305   gtk_combo_set_popdown_strings( GTK_COMBO(widget), pluginlist);
306   widget=lookup_widget( dialog_preferences, "combo_downplugin" );
307   gtk_combo_set_popdown_strings( GTK_COMBO(widget), pluginlist);
308   widget=lookup_widget( dialog_preferences, "combo_beaconplugin" );
309   gtk_combo_set_popdown_strings( GTK_COMBO(widget), pluginlist);
310 }
311 
close_rotor_plugin(void)312 void close_rotor_plugin( void )
313 {
314   if(rotorpluginenable==FALSE)
315     return;
316 
317   /* close rotor if it was open before closing plugin */
318   if( enablerotor==TRUE ) {
319     (*plugin_close_rotor)();
320     enablerotor=FALSE;
321   }
322 
323   dlclose(rotorplugin_handle);
324 
325   rotorpluginenable=FALSE;
326 }
327 
open_rotor_plugin(char * plugin)328 int open_rotor_plugin( char * plugin )
329 {
330   char * error;
331 
332   /* if it's already open, close it first */
333   if( rotorpluginenable==TRUE )
334     close_rotor_plugin();
335 
336   rotorplugin_handle=dlopen( plugin, RTLD_NOW );
337   if( rotorplugin_handle==NULL )
338     if( (error=dlerror()) != NULL ) {
339       fprintf(stderr,"Error opening rotor plugin: %s\n",error);
340       return FALSE;
341     }
342 
343   plugin_info_rotor=dlsym(rotorplugin_handle,"plugin_info");
344   if( plugin_info_rotor==NULL )
345     if( (error=dlerror()) != NULL ) {
346       fprintf(stderr,"Error: plugin_info_rotor: %s\n",error);
347       return FALSE;
348     }
349   plugin_open_rotor=dlsym(rotorplugin_handle,"plugin_open_rotor");
350   if( plugin_open_rotor==NULL )
351     if( (error=dlerror()) != NULL ) {
352       fprintf(stderr,"Error: plugin_open_rotor: %s\n",error);
353       return FALSE;
354     }
355   plugin_close_rotor=dlsym(rotorplugin_handle,"plugin_close_rotor");
356   if( plugin_close_rotor==NULL )
357     if( (error=dlerror()) != NULL ) {
358       fprintf(stderr,"Error: plugin_close_rotor: %s\n",error);
359       return FALSE;
360     }
361   plugin_set_rotor=dlsym(rotorplugin_handle,"plugin_set_rotor");
362   if( plugin_set_rotor==NULL )
363     if( (error=dlerror()) != NULL ) {
364       fprintf(stderr,"Error: plugin_set_rotor: %s\n",error);
365       return FALSE;
366     }
367 
368   rotorpluginenable=TRUE;
369 
370   return TRUE;
371 }
372 
check_rotor_plugin_file(const struct dirent * plugdir)373 int check_rotor_plugin_file( const struct dirent * plugdir )
374 {
375   return ! strncmp(plugdir->d_name,"rotor_",6);
376 }
377 
search_rotor_plugins(void)378 void search_rotor_plugins( void )
379 {
380   struct dirent **namelist;
381   int n, i;
382   GtkWidget * widget;
383   char filename[256];
384   DIR * dir;
385 
386   /* empty plugin list if it was created */
387   n = g_list_length(rotorpluginlist);
388   if( n > 0 ) {
389     rotorpluginlist=g_list_first( rotorpluginlist );
390     for( i=0; i<n; i++ )
391       rotorpluginlist=g_list_remove( rotorpluginlist, rotorpluginlist->data );
392     for( i=0; i<n; i++ ) {
393       rotorpluginfiles[i][0]='\0';
394       rotorplugindescriptions[i][0]='\0';
395     }
396   }
397 
398   strcpy( rotorpluginfiles[0], "None");
399   strcpy( rotorplugindescriptions[0], "No Plugin");
400   rotorpluginlist=g_list_append( rotorpluginlist, rotorplugindescriptions[0] );
401 
402   /* check plugin directory */
403   if( (dir=opendir( pluginsdir ))==NULL ) {
404     switch( errno ) {
405     case EACCES:
406       fprintf(stderr, "Error: You don't have access to plugin directory.\n");
407       error_dialog("You don't have access to plugin directory.");
408       break;
409     case ENOENT:
410       fprintf(stderr, "Error: Plugin directory doesn't exist.\n");
411       error_dialog("Plugin directory doesn't exist.");
412       break;
413     case ENOTDIR:
414       fprintf(stderr, "Error: Plugin directory is not a directory.\n");
415       error_dialog("Can't open plugin directory.");
416       break;
417     default:
418       fprintf(stderr, "Error: Can't open plugin directory.\n");
419       error_dialog("Can't open plugin directory.");
420       break;
421     }
422     /* Attach rotor plugin list */
423     widget=lookup_widget( dialog_preferences, "combo_rotorplugin" );
424     gtk_combo_set_popdown_strings( GTK_COMBO(widget), rotorpluginlist);
425 
426     return;
427   }
428   closedir( dir );
429 
430   /* scan plugin directory and create plugin list */
431   n = scandir(pluginsdir, &namelist, check_rotor_plugin_file, alphasort);
432   if (n < 0) {
433     perror("scandir");
434     return;
435   }
436 
437   for( i=0; i<n; i++ ) {
438     strcpy(filename, pluginsdir);
439     strcat(filename, namelist[i]->d_name);
440     if(open_rotor_plugin(filename)==TRUE) {
441       strncpy( rotorpluginfiles[i+1], namelist[i]->d_name, 29);
442       strncpy( rotorplugindescriptions[i+1], (*plugin_info_rotor)(), 29);
443       rotorpluginlist=g_list_append(rotorpluginlist, rotorplugindescriptions[i+1]);
444       close_rotor_plugin();
445     }
446   }
447 
448   /* Attach plugin list */
449   widget=lookup_widget( dialog_preferences, "combo_rotorplugin" );
450   gtk_combo_set_popdown_strings( GTK_COMBO(widget), rotorpluginlist);
451 }
452