1 /* GTK - The GIMP Toolkit
2  *
3  * Copyright (C) 2012 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Tomas Bzatek <tbzatek@redhat.com>
19  */
20 
21 #include <config.h>
22 
23 #include <stdio.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #include <locale.h>
28 #include <errno.h>
29 
30 #include <glib.h>
31 #include <glib/gi18n.h>
32 #include <gio/gio.h>
33 #if defined(HAVE_GIO_UNIX) && !defined(__APPLE__)
34 #include <gio/gdesktopappinfo.h>
35 #endif
36 #include <gtk.h>
37 
38 static gboolean show_version;
39 static gchar **args = NULL;
40 
41 static GOptionEntry entries[] = {
42   { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Show program version"), NULL },
43   { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &args, NULL, NULL },
44   { NULL}
45 };
46 
47 int
main(int argc,char * argv[])48 main (int argc, char *argv[])
49 {
50   GError *error = NULL;
51   GOptionContext *context = NULL;
52   gchar *summary;
53   gchar *app_name;
54 #ifdef G_OS_UNIX
55   gchar *desktop_file_name;
56   gchar *bus_name = NULL;
57 #endif
58   GAppInfo *info = NULL;
59   GAppLaunchContext *launch_context;
60   GList *l;
61   GFile *f;
62 
63   setlocale (LC_ALL, "");
64 
65 #ifdef ENABLE_NLS
66   bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
67   textdomain (GETTEXT_PACKAGE);
68 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
69   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
70 #endif
71 #endif
72 
73   /* Translators: this message will appear immediately after the */
74   /* usage string - Usage: COMMAND [OPTION...] <THIS_MESSAGE>    */
75   context =
76     g_option_context_new (_("APPLICATION [URI...] — launch an APPLICATION"));
77 
78   /* Translators: this message will appear after the usage string */
79   /* and before the list of options.                              */
80   summary = _("Launch an application (specified by its desktop file name),\n"
81               "optionally passing one or more URIs as arguments.");
82   g_option_context_set_summary (context, summary);
83   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
84   g_option_context_add_group (context, gtk_get_option_group (FALSE));
85 
86   g_option_context_parse (context, &argc, &argv, &error);
87 
88   g_option_context_free (context);
89 
90   if (error != NULL)
91     {
92       g_printerr (_("Error parsing commandline options: %s\n"), error->message);
93       g_printerr ("\n");
94       g_printerr (_("Try \"%s --help\" for more information."), g_get_prgname ());
95       g_printerr ("\n");
96       g_error_free (error);
97       return 1;
98     }
99 
100   if (show_version)
101     {
102       g_print ("%d.%d.%d\n",
103                gtk_get_major_version (),
104                gtk_get_minor_version (),
105                gtk_get_micro_version ());
106       return 0;
107     }
108 
109   if (!args)
110     {
111       /* Translators: the %s is the program name. This error message */
112       /* means the user is calling gtk-launch without any argument.  */
113       g_printerr (_("%s: missing application name"), g_get_prgname ());
114       g_printerr ("\n");
115       g_printerr (_("Try \"%s --help\" for more information."), g_get_prgname ());
116       g_printerr ("\n");
117       return 1;
118     }
119 
120 
121   gtk_init (&argc, &argv);
122 
123   app_name = *args;
124 #if defined(HAVE_GIO_UNIX) && !defined(__APPLE__)
125   bus_name = g_strdup (app_name);
126   if (g_str_has_suffix (app_name, ".desktop"))
127     {
128       desktop_file_name = g_strdup (app_name);
129       bus_name[strlen (bus_name) - strlen(".desktop")] = '\0';
130     }
131   else
132     {
133       desktop_file_name = g_strconcat (app_name, ".desktop", NULL);
134     }
135 
136   if (!g_dbus_is_name (bus_name))
137     g_clear_pointer (&bus_name, g_free);
138   info = G_APP_INFO (g_desktop_app_info_new (desktop_file_name));
139   g_free (desktop_file_name);
140 #else
141   #ifndef _MSC_VER
142     #warning Please add support for creating AppInfo from id for your OS
143   #endif
144   g_printerr (_("Creating AppInfo from id not supported on non unix operating systems"));
145 #endif
146   args++;
147 
148   if (!info)
149     {
150       /* Translators: the first %s is the program name, the second one */
151       /* is the application name.                                      */
152       g_printerr (_("%s: no such application %s"),
153                   g_get_prgname (), app_name);
154       g_printerr ("\n");
155       return 2;
156     }
157 
158   l = NULL;
159   for (; *args; args++)
160     {
161       f = g_file_new_for_commandline_arg (*args);
162       l = g_list_append (l, f);
163     }
164 
165   launch_context = (GAppLaunchContext*) gdk_display_get_app_launch_context (gdk_display_get_default ());
166   if (!g_app_info_launch (info, l, launch_context, &error))
167     {
168        /* Translators: the first %s is the program name, the second one  */
169        /* is the error message.                                          */
170        g_printerr (_("%s: error launching application: %s\n"),
171                    g_get_prgname (), error->message);
172        return 3;
173     }
174   g_object_unref (info);
175   g_object_unref (launch_context);
176 
177 #ifdef G_OS_UNIX
178   if (bus_name != NULL)
179     {
180       GDBusConnection *connection;
181       gchar *object_path, *p;
182 
183       connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
184 
185       object_path = g_strdup_printf ("/%s", bus_name);
186       for (p = object_path; *p != '\0'; p++)
187           if (*p == '.')
188               *p = '/';
189 
190       if (connection)
191         g_dbus_connection_call_sync (connection,
192                                      bus_name,
193                                      object_path,
194                                      "org.freedesktop.DBus.Peer",
195                                      "Ping",
196                                      NULL, NULL,
197                                      G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL);
198       g_clear_pointer (&object_path, g_free);
199       g_clear_object (&connection);
200       g_clear_pointer (&bus_name, g_free);
201     }
202 #endif
203   g_list_free_full (l, g_object_unref);
204 
205   return 0;
206 }
207