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 | #include <unistd.h> |
25 | #include <locale.h> |
26 | #include <errno.h> |
27 | |
28 | #include <glib.h> |
29 | #include <glib/gi18n.h> |
30 | #include <gio/gio.h> |
31 | #if defined(HAVE_GIO_UNIX) && !defined(__APPLE__) |
32 | #include <gio/gdesktopappinfo.h> |
33 | #endif |
34 | #include <gtk.h> |
35 | |
36 | static gboolean show_version; |
37 | static char **args = NULL; |
38 | |
39 | static GOptionEntry entries[] = { |
40 | { "version" , 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Show program version" ), NULL }, |
41 | { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &args, NULL, NULL }, |
42 | { NULL} |
43 | }; |
44 | |
45 | int |
46 | main (int argc, char *argv[]) |
47 | { |
48 | GError *error = NULL; |
49 | GOptionContext *context = NULL; |
50 | char *summary; |
51 | char *app_name; |
52 | #ifdef G_OS_UNIX |
53 | char *desktop_file_name; |
54 | char *bus_name = NULL; |
55 | #endif |
56 | GAppInfo *info = NULL; |
57 | GAppLaunchContext *launch_context; |
58 | GList *l; |
59 | GFile *f; |
60 | |
61 | setlocale (LC_ALL, locale: "" ); |
62 | |
63 | bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR); |
64 | textdomain (GETTEXT_PACKAGE); |
65 | #ifdef HAVE_BIND_TEXTDOMAIN_CODESET |
66 | bind_textdomain_codeset (GETTEXT_PACKAGE, codeset: "UTF-8" ); |
67 | #endif |
68 | |
69 | context = |
70 | /* Translators: this message will appear immediately after the */ |
71 | /* usage string - Usage: COMMAND [OPTION…] <THIS_MESSAGE> */ |
72 | g_option_context_new (_("APPLICATION [URI…] — launch an APPLICATION" )); |
73 | |
74 | /* Translators: this message will appear after the usage string */ |
75 | /* and before the list of options. */ |
76 | summary = _("Launch an application (specified by its desktop file name),\n" |
77 | "optionally passing one or more URIs as arguments." ); |
78 | g_option_context_set_summary (context, summary); |
79 | g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); |
80 | g_option_context_parse (context, argc: &argc, argv: &argv, error: &error); |
81 | |
82 | g_option_context_free (context); |
83 | |
84 | if (error != NULL) |
85 | { |
86 | g_printerr (_("Error parsing commandline options: %s\n" ), error->message); |
87 | g_printerr (format: "\n" ); |
88 | g_printerr (_("Try “%s --help” for more information." ), g_get_prgname ()); |
89 | g_printerr (format: "\n" ); |
90 | g_error_free (error); |
91 | return 1; |
92 | } |
93 | |
94 | if (show_version) |
95 | { |
96 | g_print (format: "%d.%d.%d\n" , |
97 | gtk_get_major_version (), |
98 | gtk_get_minor_version (), |
99 | gtk_get_micro_version ()); |
100 | return 0; |
101 | } |
102 | |
103 | if (!args) |
104 | { |
105 | /* Translators: the %s is the program name. This error message */ |
106 | /* means the user is calling gtk-launch without any argument. */ |
107 | g_printerr (_("%s: missing application name" ), g_get_prgname ()); |
108 | g_printerr (format: "\n" ); |
109 | g_printerr (_("Try “%s --help” for more information." ), g_get_prgname ()); |
110 | g_printerr (format: "\n" ); |
111 | return 1; |
112 | } |
113 | |
114 | |
115 | gtk_init (); |
116 | |
117 | app_name = *args; |
118 | #if defined(HAVE_GIO_UNIX) && !defined(__APPLE__) |
119 | bus_name = g_strdup (str: app_name); |
120 | if (g_str_has_suffix (str: app_name, suffix: ".desktop" )) |
121 | { |
122 | desktop_file_name = g_strdup (str: app_name); |
123 | bus_name[strlen (s: bus_name) - strlen(s: ".desktop" )] = '\0'; |
124 | } |
125 | else |
126 | { |
127 | desktop_file_name = g_strconcat (string1: app_name, ".desktop" , NULL); |
128 | } |
129 | |
130 | if (!g_dbus_is_name (string: bus_name)) |
131 | g_clear_pointer (&bus_name, g_free); |
132 | info = G_APP_INFO (g_desktop_app_info_new (desktop_file_name)); |
133 | g_free (mem: desktop_file_name); |
134 | #else |
135 | #warning Please add support for creating AppInfo from id for your OS |
136 | g_printerr (_("Creating AppInfo from id not supported on non unix operating systems" )); |
137 | #endif |
138 | args++; |
139 | |
140 | if (!info) |
141 | { |
142 | /* Translators: the first %s is the program name, the second one */ |
143 | /* is the application name. */ |
144 | g_printerr (_("%s: no such application %s" ), |
145 | g_get_prgname (), app_name); |
146 | g_printerr (format: "\n" ); |
147 | return 2; |
148 | } |
149 | |
150 | l = NULL; |
151 | for (; *args; args++) |
152 | { |
153 | f = g_file_new_for_commandline_arg (arg: *args); |
154 | l = g_list_append (list: l, data: f); |
155 | } |
156 | |
157 | launch_context = (GAppLaunchContext*) gdk_display_get_app_launch_context (display: gdk_display_get_default ()); |
158 | if (!g_app_info_launch (appinfo: info, files: l, context: launch_context, error: &error)) |
159 | { |
160 | /* Translators: the first %s is the program name, the second one */ |
161 | /* is the error message. */ |
162 | g_printerr (_("%s: error launching application: %s\n" ), |
163 | g_get_prgname (), error->message); |
164 | return 3; |
165 | } |
166 | g_object_unref (object: info); |
167 | g_object_unref (object: launch_context); |
168 | |
169 | #ifdef G_OS_UNIX |
170 | if (bus_name != NULL) |
171 | { |
172 | GDBusConnection *connection; |
173 | char *object_path, *p; |
174 | |
175 | connection = g_bus_get_sync (bus_type: G_BUS_TYPE_SESSION, NULL, NULL); |
176 | |
177 | object_path = g_strdup_printf (format: "/%s" , bus_name); |
178 | for (p = object_path; *p != '\0'; p++) |
179 | if (*p == '.') |
180 | *p = '/'; |
181 | |
182 | if (connection) |
183 | g_dbus_connection_call_sync (connection, |
184 | bus_name, |
185 | object_path, |
186 | interface_name: "org.freedesktop.DBus.Peer" , |
187 | method_name: "Ping" , |
188 | NULL, NULL, |
189 | flags: G_DBUS_CALL_FLAGS_NONE, timeout_msec: -1, NULL, NULL); |
190 | g_clear_pointer (&object_path, g_free); |
191 | g_clear_object (&connection); |
192 | g_clear_pointer (&bus_name, g_free); |
193 | } |
194 | #endif |
195 | g_list_free_full (list: l, free_func: g_object_unref); |
196 | |
197 | return 0; |
198 | } |
199 | |