Remmina - The GTK+ Remote Desktop Client  v1.4.2
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
remmina_external_tools.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2011 Marc-Andre Moreau
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * In addition, as a special exception, the copyright holders give
21  * permission to link the code of portions of this program with the
22  * OpenSSL library under certain conditions as described in each
23  * individual source file, and distribute linked combinations
24  * including the two.
25  * You must obey the GNU General Public License in all respects
26  * for all of the code used other than OpenSSL. * If you modify
27  * file(s) with this exception, you may extend this exception to your
28  * version of the file(s), but you are not obligated to do so. * If you
29  * do not wish to do so, delete this exception statement from your
30  * version. * If you delete this exception statement from all source
31  * files in the program, then also delete it here.
32  *
33  */
34 
35 #include <gtk/gtk.h>
36 #include <glib/gi18n.h>
37 #include <glib/gstdio.h>
38 #include <stdlib.h>
39 #include "remmina/types.h"
40 #include "remmina_public.h"
41 #include "remmina_external_tools.h"
43 
44 static gboolean remmina_external_tools_launcher(const gchar* filename, const gchar* scriptname, const gchar* shortname);
45 
46 static void view_popup_menu_onDoSomething(GtkWidget *menuitem, gpointer userdata)
47 {
48  TRACE_CALL(__func__);
49  gchar *remminafilename = g_object_get_data(G_OBJECT(menuitem), "remminafilename");
50  gchar *scriptfilename = g_object_get_data(G_OBJECT(menuitem), "scriptfilename");
51  gchar *scriptshortname = g_object_get_data(G_OBJECT(menuitem), "scriptshortname");
52 
53  remmina_external_tools_launcher(remminafilename, scriptfilename, scriptshortname);
54 }
55 
57 {
58  TRACE_CALL(__func__);
59  GtkWidget *menu, *menuitem;
60  gchar dirname[MAX_PATH_LEN];
61  gchar filename[MAX_PATH_LEN];
62  GDir* dir;
63  const gchar* name;
64 
65  strcpy(dirname, REMMINA_RUNTIME_EXTERNAL_TOOLS_DIR);
66  dir = g_dir_open(dirname, 0, NULL);
67 
68  if (dir == NULL)
69  return FALSE;
70 
71  menu = gtk_menu_new();
72 
73  while ((name = g_dir_read_name(dir)) != NULL) {
74  if (!g_str_has_prefix(name, "remmina_"))
75  continue;
76  g_snprintf(filename, MAX_PATH_LEN, "%s/%s", dirname, name);
77 
78  menuitem = gtk_menu_item_new_with_label(name + 8);
79  g_object_set_data_full(G_OBJECT(menuitem), "remminafilename", g_strdup(remminafilename), g_free);
80  g_object_set_data_full(G_OBJECT(menuitem), "scriptfilename", g_strdup(filename), g_free);
81  g_object_set_data_full(G_OBJECT(menuitem), "scriptshortname", g_strdup(name), g_free);
82  g_signal_connect(menuitem, "activate", (GCallback)view_popup_menu_onDoSomething, NULL);
83  gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
84  }
85  g_dir_close(dir);
86 
87  gtk_widget_show_all(menu);
88 
89  /* Note: event can be NULL here when called from view_onPopupMenu;
90  * gdk_event_get_time() accepts a NULL argument
91  */
92 #if GTK_CHECK_VERSION(3, 22, 0)
93  gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
94 #else
95  gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
96 #endif
97 
98  return TRUE;
99 }
100 
101 static gboolean remmina_external_tools_launcher(const gchar* filename, const gchar* scriptname, const gchar* shortname)
102 {
103  TRACE_CALL(__func__);
104  RemminaFile *remminafile;
105  const char *env_format = "%s=%s";
106  char *env;
107  size_t envstrlen;
108  gchar launcher[MAX_PATH_LEN];
109 
110  g_snprintf(launcher, MAX_PATH_LEN, "%s/launcher.sh", REMMINA_RUNTIME_EXTERNAL_TOOLS_DIR);
111 
112  remminafile = remmina_file_load(filename);
113  if (!remminafile)
114  return FALSE;
115  GHashTableIter iter;
116  const gchar *key, *value;
117  g_hash_table_iter_init(&iter, remminafile->settings);
118  while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value)) {
119  envstrlen = strlen(key) + strlen(value) + strlen(env_format) + 1;
120  env = (char*)malloc(envstrlen);
121  if (env == NULL) {
122  return -1;
123  }
124 
125  int retval = snprintf(env, envstrlen, env_format, key, value);
126  if (retval > 0 && (size_t)retval <= envstrlen) {
127  if (putenv(env) != 0) {
128  /* If putenv fails, we must free the unused space */
129  free(env);
130  }
131  }
132  }
133  /* Adds the window title for the terminal window */
134  const char *term_title_key = "remmina_term_title";
135  const char *term_title_val_prefix = "Remmina external tool";
136  envstrlen = strlen(term_title_key) + strlen(term_title_val_prefix) + strlen(shortname) + 7;
137  env = (char*)malloc(envstrlen);
138  if (env != NULL) {
139  if (snprintf(env, envstrlen, "%s=%s: %s", term_title_key, term_title_val_prefix, shortname) ) {
140  if (putenv(env) != 0) {
141  /* If putenv fails, we must free the unused space */
142  free(env);
143  }
144  }
145  }
146 
147  const size_t cmdlen = strlen(launcher) + strlen(scriptname) + 2;
148  gchar *cmd = (gchar*)malloc(cmdlen);
149  g_snprintf(cmd, cmdlen, "%s %s", launcher, scriptname);
150  system(cmd);
151  free(cmd);
152 
153  remmina_file_free(remminafile);
154 
155  return TRUE;
156 }
RemminaFile * remmina_file_load(const gchar *filename)
Definition: remmina_file.c:327
void remmina_file_free(RemminaFile *remminafile)
Definition: remmina_file.c:548
static gboolean remmina_external_tools_launcher(const gchar *filename, const gchar *scriptname, const gchar *shortname)
gboolean remmina_external_tools_from_filename(RemminaMain *remminamain, gchar *remminafilename)
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:41
static RemminaMain * remminamain
Definition: remmina_main.c:65
static void view_popup_menu_onDoSomething(GtkWidget *menuitem, gpointer userdata)