Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2010 Codethink Limited
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful, but
12 : : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General Public
17 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : *
19 : : * Authors: Ryan Lortie <desrt@desrt.ca>
20 : : */
21 : :
22 : : #include "config.h"
23 : :
24 : : #include "gapplicationcommandline.h"
25 : :
26 : : #include "glibintl.h"
27 : : #include "gfile.h"
28 : :
29 : : #include <string.h>
30 : : #include <stdio.h>
31 : :
32 : : #ifdef G_OS_UNIX
33 : : #include "gunixinputstream.h"
34 : : #endif
35 : :
36 : : #ifdef G_OS_WIN32
37 : : #include <windows.h>
38 : : #undef environ
39 : : #include "gwin32inputstream.h"
40 : : #endif
41 : :
42 : : /**
43 : : * GApplicationCommandLine:
44 : : *
45 : : * `GApplicationCommandLine` represents a command-line invocation of
46 : : * an application.
47 : : *
48 : : * It is created by [class@Gio.Application] and emitted
49 : : * in the [signal@Gio.Application::command-line] signal and virtual function.
50 : : *
51 : : * The class contains the list of arguments that the program was invoked
52 : : * with. It is also possible to query if the commandline invocation was
53 : : * local (ie: the current process is running in direct response to the
54 : : * invocation) or remote (ie: some other process forwarded the
55 : : * commandline to this process).
56 : : *
57 : : * The `GApplicationCommandLine` object can provide the @argc and @argv
58 : : * parameters for use with the [struct@GLib.OptionContext] command-line parsing API,
59 : : * with the [method@Gio.ApplicationCommandLine.get_arguments] function. See
60 : : * [gapplication-example-cmdline3.c][gapplication-example-cmdline3]
61 : : * for an example.
62 : : *
63 : : * The exit status of the originally-invoked process may be set and
64 : : * messages can be printed to stdout or stderr of that process.
65 : : *
66 : : * For remote invocation, the originally-invoked process exits when
67 : : * [method@Gio.ApplicationCommandLine.done] method is called. This method is
68 : : * also automatically called when the object is disposed.
69 : : *
70 : : * The main use for `GApplicationCommandLine` (and the
71 : : * [signal@Gio.Application::command-line] signal) is 'Emacs server' like use cases:
72 : : * You can set the `EDITOR` environment variable to have e.g. git use
73 : : * your favourite editor to edit commit messages, and if you already
74 : : * have an instance of the editor running, the editing will happen
75 : : * in the running instance, instead of opening a new one. An important
76 : : * aspect of this use case is that the process that gets started by git
77 : : * does not return until the editing is done.
78 : : *
79 : : * Normally, the commandline is completely handled in the
80 : : * [signal@Gio.Application::command-line] handler. The launching instance exits
81 : : * once the signal handler in the primary instance has returned, and
82 : : * the return value of the signal handler becomes the exit status
83 : : * of the launching instance.
84 : : *
85 : : * ```c
86 : : * static int
87 : : * command_line (GApplication *application,
88 : : * GApplicationCommandLine *cmdline)
89 : : * {
90 : : * gchar **argv;
91 : : * gint argc;
92 : : * gint i;
93 : : *
94 : : * argv = g_application_command_line_get_arguments (cmdline, &argc);
95 : : *
96 : : * g_application_command_line_print (cmdline,
97 : : * "This text is written back\n"
98 : : * "to stdout of the caller\n");
99 : : *
100 : : * for (i = 0; i < argc; i++)
101 : : * g_print ("argument %d: %s\n", i, argv[i]);
102 : : *
103 : : * g_strfreev (argv);
104 : : *
105 : : * return 0;
106 : : * }
107 : : * ```
108 : : *
109 : : * The complete example can be found here:
110 : : * [gapplication-example-cmdline.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-cmdline.c)
111 : : *
112 : : * In more complicated cases, the handling of the commandline can be
113 : : * split between the launcher and the primary instance.
114 : : *
115 : : * ```c
116 : : * static gboolean
117 : : * test_local_cmdline (GApplication *application,
118 : : * gchar ***arguments,
119 : : * gint *exit_status)
120 : : * {
121 : : * gint i, j;
122 : : * gchar **argv;
123 : : *
124 : : * argv = *arguments;
125 : : *
126 : : * if (argv[0] == NULL)
127 : : * {
128 : : * *exit_status = 0;
129 : : * return FALSE;
130 : : * }
131 : : *
132 : : * i = 1;
133 : : * while (argv[i])
134 : : * {
135 : : * if (g_str_has_prefix (argv[i], "--local-"))
136 : : * {
137 : : * g_print ("handling argument %s locally\n", argv[i]);
138 : : * g_free (argv[i]);
139 : : * for (j = i; argv[j]; j++)
140 : : * argv[j] = argv[j + 1];
141 : : * }
142 : : * else
143 : : * {
144 : : * g_print ("not handling argument %s locally\n", argv[i]);
145 : : * i++;
146 : : * }
147 : : * }
148 : : *
149 : : * *exit_status = 0;
150 : : *
151 : : * return FALSE;
152 : : * }
153 : : *
154 : : * static void
155 : : * test_application_class_init (TestApplicationClass *class)
156 : : * {
157 : : * G_APPLICATION_CLASS (class)->local_command_line = test_local_cmdline;
158 : : *
159 : : * ...
160 : : * }
161 : : * ```
162 : : *
163 : : * In this example of split commandline handling, options that start
164 : : * with `--local-` are handled locally, all other options are passed
165 : : * to the [signal@Gio.Application::command-line] handler which runs in the primary
166 : : * instance.
167 : : *
168 : : * The complete example can be found here:
169 : : * [gapplication-example-cmdline2.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-cmdline2.c)
170 : : *
171 : : * If handling the commandline requires a lot of work, it may be better to defer it.
172 : : *
173 : : * ```c
174 : : * static gboolean
175 : : * my_cmdline_handler (gpointer data)
176 : : * {
177 : : * GApplicationCommandLine *cmdline = data;
178 : : *
179 : : * // do the heavy lifting in an idle
180 : : *
181 : : * g_application_command_line_set_exit_status (cmdline, 0);
182 : : * g_object_unref (cmdline); // this releases the application
183 : : *
184 : : * return G_SOURCE_REMOVE;
185 : : * }
186 : : *
187 : : * static int
188 : : * command_line (GApplication *application,
189 : : * GApplicationCommandLine *cmdline)
190 : : * {
191 : : * // keep the application running until we are done with this commandline
192 : : * g_application_hold (application);
193 : : *
194 : : * g_object_set_data_full (G_OBJECT (cmdline),
195 : : * "application", application,
196 : : * (GDestroyNotify)g_application_release);
197 : : *
198 : : * g_object_ref (cmdline);
199 : : * g_idle_add (my_cmdline_handler, cmdline);
200 : : *
201 : : * return 0;
202 : : * }
203 : : * ```
204 : : *
205 : : * In this example the commandline is not completely handled before
206 : : * the [signal@Gio.Application::command-line] handler returns. Instead, we keep
207 : : * a reference to the `GApplicationCommandLine` object and handle it
208 : : * later (in this example, in an idle). Note that it is necessary to
209 : : * hold the application until you are done with the commandline.
210 : : *
211 : : * The complete example can be found here:
212 : : * [gapplication-example-cmdline3.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-cmdline3.c)
213 : : */
214 : :
215 : : /**
216 : : * GApplicationCommandLineClass:
217 : : *
218 : : * The #GApplicationCommandLineClass-struct
219 : : * contains private data only.
220 : : *
221 : : * Since: 2.28
222 : : **/
223 : : enum
224 : : {
225 : : PROP_NONE,
226 : : PROP_ARGUMENTS,
227 : : PROP_OPTIONS,
228 : : PROP_PLATFORM_DATA,
229 : : PROP_IS_REMOTE
230 : : };
231 : :
232 : : struct _GApplicationCommandLinePrivate
233 : : {
234 : : GVariant *platform_data;
235 : : GVariant *arguments;
236 : : GVariant *options;
237 : : GVariantDict *options_dict;
238 : : gchar *cwd; /* in GLib filename encoding, not UTF-8 */
239 : :
240 : : gchar **environ;
241 : : gint exit_status;
242 : : gboolean done;
243 : : };
244 : :
245 : 183 : G_DEFINE_TYPE_WITH_PRIVATE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJECT)
246 : :
247 : : /* All subclasses represent remote invocations of some kind. */
248 : : #define IS_REMOTE(cmdline) (G_TYPE_FROM_INSTANCE (cmdline) != \
249 : : G_TYPE_APPLICATION_COMMAND_LINE)
250 : :
251 : : static void
252 : 5 : grok_platform_data (GApplicationCommandLine *cmdline)
253 : : {
254 : : GVariantIter iter;
255 : : const gchar *key;
256 : : GVariant *value;
257 : :
258 : 5 : g_variant_iter_init (&iter, cmdline->priv->platform_data);
259 : :
260 : 13 : while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
261 : 8 : if (strcmp (key, "cwd") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING))
262 : : {
263 : 1 : if (!cmdline->priv->cwd)
264 : 1 : cmdline->priv->cwd = g_variant_dup_bytestring (value, NULL);
265 : : }
266 : :
267 : 7 : else if (strcmp (key, "environ") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING_ARRAY))
268 : : {
269 : 1 : if (!cmdline->priv->environ)
270 : 1 : cmdline->priv->environ =
271 : 1 : g_variant_dup_bytestring_array (value, NULL);
272 : : }
273 : :
274 : 6 : else if (strcmp (key, "options") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_VARDICT))
275 : : {
276 : 1 : if (!cmdline->priv->options)
277 : 1 : cmdline->priv->options = g_variant_ref (value);
278 : : }
279 : 5 : }
280 : :
281 : : static void
282 : 0 : g_application_command_line_real_print_literal (GApplicationCommandLine *cmdline,
283 : : const gchar *message)
284 : : {
285 : 0 : g_print ("%s", message);
286 : 0 : }
287 : :
288 : : static void
289 : 0 : g_application_command_line_real_printerr_literal (GApplicationCommandLine *cmdline,
290 : : const gchar *message)
291 : : {
292 : 0 : g_printerr ("%s", message);
293 : 0 : }
294 : :
295 : : static GInputStream *
296 : 0 : g_application_command_line_real_get_stdin (GApplicationCommandLine *cmdline)
297 : : {
298 : : #ifdef G_OS_UNIX
299 : 0 : return g_unix_input_stream_new (0, FALSE);
300 : : #else
301 : : return g_win32_input_stream_new (GetStdHandle (STD_INPUT_HANDLE), FALSE);
302 : : #endif
303 : : }
304 : :
305 : : static void
306 : 11 : g_application_command_line_real_done (GApplicationCommandLine *cmdline)
307 : : {
308 : 11 : }
309 : :
310 : : static void
311 : 2 : g_application_command_line_get_property (GObject *object,
312 : : guint prop_id,
313 : : GValue *value,
314 : : GParamSpec *pspec)
315 : : {
316 : 2 : GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
317 : :
318 : 2 : switch (prop_id)
319 : : {
320 : 0 : case PROP_ARGUMENTS:
321 : 0 : g_value_set_variant (value, cmdline->priv->arguments);
322 : 0 : break;
323 : :
324 : 0 : case PROP_PLATFORM_DATA:
325 : 0 : g_value_set_variant (value, cmdline->priv->platform_data);
326 : 0 : break;
327 : :
328 : 2 : case PROP_IS_REMOTE:
329 : 2 : g_value_set_boolean (value, IS_REMOTE (cmdline));
330 : 2 : break;
331 : :
332 : 0 : default:
333 : : g_assert_not_reached ();
334 : : }
335 : 2 : }
336 : :
337 : : static void
338 : 33 : g_application_command_line_set_property (GObject *object,
339 : : guint prop_id,
340 : : const GValue *value,
341 : : GParamSpec *pspec)
342 : : {
343 : 33 : GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
344 : :
345 : 33 : switch (prop_id)
346 : : {
347 : 11 : case PROP_ARGUMENTS:
348 : 11 : g_assert (cmdline->priv->arguments == NULL);
349 : 11 : cmdline->priv->arguments = g_value_dup_variant (value);
350 : 11 : break;
351 : :
352 : 11 : case PROP_OPTIONS:
353 : 11 : g_assert (cmdline->priv->options == NULL);
354 : 11 : cmdline->priv->options = g_value_dup_variant (value);
355 : 11 : break;
356 : :
357 : 11 : case PROP_PLATFORM_DATA:
358 : 11 : g_assert (cmdline->priv->platform_data == NULL);
359 : 11 : cmdline->priv->platform_data = g_value_dup_variant (value);
360 : 11 : if (cmdline->priv->platform_data != NULL)
361 : 5 : grok_platform_data (cmdline);
362 : 11 : break;
363 : :
364 : 0 : default:
365 : : g_assert_not_reached ();
366 : : }
367 : 33 : }
368 : :
369 : : static void
370 : 11 : g_application_command_line_dispose (GObject *object)
371 : : {
372 : 11 : GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
373 : :
374 : 11 : g_application_command_line_done (cmdline);
375 : :
376 : 11 : G_OBJECT_CLASS (g_application_command_line_parent_class)->dispose (object);
377 : 11 : }
378 : :
379 : : static void
380 : 11 : g_application_command_line_finalize (GObject *object)
381 : : {
382 : 11 : GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
383 : :
384 : 11 : if (cmdline->priv->options_dict)
385 : 1 : g_variant_dict_unref (cmdline->priv->options_dict);
386 : :
387 : 11 : if (cmdline->priv->options)
388 : 7 : g_variant_unref (cmdline->priv->options);
389 : :
390 : 11 : if (cmdline->priv->platform_data)
391 : 5 : g_variant_unref (cmdline->priv->platform_data);
392 : 11 : if (cmdline->priv->arguments)
393 : 10 : g_variant_unref (cmdline->priv->arguments);
394 : :
395 : 11 : g_free (cmdline->priv->cwd);
396 : 11 : g_strfreev (cmdline->priv->environ);
397 : :
398 : 11 : G_OBJECT_CLASS (g_application_command_line_parent_class)
399 : 11 : ->finalize (object);
400 : 11 : }
401 : :
402 : : static void
403 : 11 : g_application_command_line_init (GApplicationCommandLine *cmdline)
404 : : {
405 : 11 : cmdline->priv = g_application_command_line_get_instance_private (cmdline);
406 : 11 : }
407 : :
408 : : static void
409 : 11 : g_application_command_line_constructed (GObject *object)
410 : : {
411 : 11 : GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
412 : :
413 : 11 : if (IS_REMOTE (cmdline))
414 : 4 : return;
415 : :
416 : : /* In the local case, set cmd and environ */
417 : 7 : if (!cmdline->priv->cwd)
418 : 7 : cmdline->priv->cwd = g_get_current_dir ();
419 : :
420 : 7 : if (!cmdline->priv->environ)
421 : 7 : cmdline->priv->environ = g_get_environ ();
422 : : }
423 : :
424 : : static void
425 : 4 : g_application_command_line_class_init (GApplicationCommandLineClass *class)
426 : : {
427 : 4 : GObjectClass *object_class = G_OBJECT_CLASS (class);
428 : :
429 : 4 : object_class->get_property = g_application_command_line_get_property;
430 : 4 : object_class->set_property = g_application_command_line_set_property;
431 : 4 : object_class->finalize = g_application_command_line_finalize;
432 : 4 : object_class->dispose = g_application_command_line_dispose;
433 : 4 : object_class->constructed = g_application_command_line_constructed;
434 : :
435 : 4 : class->printerr_literal = g_application_command_line_real_printerr_literal;
436 : 4 : class->print_literal = g_application_command_line_real_print_literal;
437 : 4 : class->get_stdin = g_application_command_line_real_get_stdin;
438 : :
439 : 4 : class->done = g_application_command_line_real_done;
440 : :
441 : : /**
442 : : * GApplicationCommandLine:arguments:
443 : : *
444 : : * The commandline that caused this [signal@Gio.Application::command-line]
445 : : * signal emission.
446 : : *
447 : : * Since: 2.28
448 : : */
449 : 4 : g_object_class_install_property (object_class, PROP_ARGUMENTS,
450 : : g_param_spec_variant ("arguments", NULL, NULL,
451 : : G_VARIANT_TYPE_BYTESTRING_ARRAY, NULL,
452 : : G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
453 : : G_PARAM_STATIC_STRINGS));
454 : :
455 : : /**
456 : : * GApplicationCommandLine:options:
457 : : *
458 : : * The options sent along with the commandline.
459 : : *
460 : : * Since: 2.28
461 : : */
462 : 4 : g_object_class_install_property (object_class, PROP_OPTIONS,
463 : : g_param_spec_variant ("options", NULL, NULL,
464 : : G_VARIANT_TYPE_VARDICT, NULL, G_PARAM_WRITABLE |
465 : : G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
466 : :
467 : : /**
468 : : * GApplicationCommandLine:platform-data:
469 : : *
470 : : * Platform-specific data for the commandline.
471 : : *
472 : : * Since: 2.28
473 : : */
474 : 4 : g_object_class_install_property (object_class, PROP_PLATFORM_DATA,
475 : : g_param_spec_variant ("platform-data", NULL, NULL,
476 : : G_VARIANT_TYPE ("a{sv}"), NULL,
477 : : G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
478 : : G_PARAM_STATIC_STRINGS));
479 : :
480 : : /**
481 : : * GApplicationCommandLine:is-remote:
482 : : *
483 : : * Whether this is a remote commandline.
484 : : *
485 : : * Since: 2.28
486 : : */
487 : 4 : g_object_class_install_property (object_class, PROP_IS_REMOTE,
488 : : g_param_spec_boolean ("is-remote", NULL, NULL,
489 : : FALSE,
490 : : G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
491 : 4 : }
492 : :
493 : :
494 : : /**
495 : : * g_application_command_line_get_arguments:
496 : : * @cmdline: a #GApplicationCommandLine
497 : : * @argc: (out) (optional): the length of the arguments array, or %NULL
498 : : *
499 : : * Gets the list of arguments that was passed on the command line.
500 : : *
501 : : * The strings in the array may contain non-UTF-8 data on UNIX (such as
502 : : * filenames or arguments given in the system locale) but are always in
503 : : * UTF-8 on Windows.
504 : : *
505 : : * If you wish to use the return value with #GOptionContext, you must
506 : : * use g_option_context_parse_strv().
507 : : *
508 : : * The return value is %NULL-terminated and should be freed using
509 : : * g_strfreev().
510 : : *
511 : : * Returns: (array length=argc) (element-type filename) (transfer full)
512 : : * the string array containing the arguments (the argv)
513 : : *
514 : : * Since: 2.28
515 : : **/
516 : : gchar **
517 : 1 : g_application_command_line_get_arguments (GApplicationCommandLine *cmdline,
518 : : int *argc)
519 : : {
520 : : gchar **argv;
521 : : gsize len;
522 : :
523 : 1 : g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
524 : :
525 : 1 : argv = g_variant_dup_bytestring_array (cmdline->priv->arguments, &len);
526 : :
527 : 1 : if (argc)
528 : 1 : *argc = len;
529 : :
530 : 1 : return argv;
531 : : }
532 : :
533 : : /**
534 : : * g_application_command_line_get_options_dict:
535 : : * @cmdline: a #GApplicationCommandLine
536 : : *
537 : : * Gets the options that were passed to g_application_command_line().
538 : : *
539 : : * If you did not override local_command_line() then these are the same
540 : : * options that were parsed according to the #GOptionEntrys added to the
541 : : * application with g_application_add_main_option_entries() and possibly
542 : : * modified from your GApplication::handle-local-options handler.
543 : : *
544 : : * If no options were sent then an empty dictionary is returned so that
545 : : * you don't need to check for %NULL.
546 : : *
547 : : * The data has been passed via an untrusted external process, so the types of
548 : : * all values must be checked before being used.
549 : : *
550 : : * Returns: (transfer none): a #GVariantDict with the options
551 : : *
552 : : * Since: 2.40
553 : : **/
554 : : GVariantDict *
555 : 1 : g_application_command_line_get_options_dict (GApplicationCommandLine *cmdline)
556 : : {
557 : 1 : g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
558 : :
559 : 1 : if (!cmdline->priv->options_dict)
560 : 1 : cmdline->priv->options_dict = g_variant_dict_new (cmdline->priv->options);
561 : :
562 : 1 : return cmdline->priv->options_dict;
563 : : }
564 : :
565 : : /**
566 : : * g_application_command_line_get_stdin:
567 : : * @cmdline: a #GApplicationCommandLine
568 : : *
569 : : * Gets the stdin of the invoking process.
570 : : *
571 : : * The #GInputStream can be used to read data passed to the standard
572 : : * input of the invoking process.
573 : : * This doesn't work on all platforms. Presently, it is only available
574 : : * on UNIX when using a D-Bus daemon capable of passing file descriptors.
575 : : * If stdin is not available then %NULL will be returned. In the
576 : : * future, support may be expanded to other platforms.
577 : : *
578 : : * You must only call this function once per commandline invocation.
579 : : *
580 : : * Returns: (nullable) (transfer full): a #GInputStream for stdin
581 : : *
582 : : * Since: 2.34
583 : : **/
584 : : GInputStream *
585 : 0 : g_application_command_line_get_stdin (GApplicationCommandLine *cmdline)
586 : : {
587 : 0 : return G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)->get_stdin (cmdline);
588 : : }
589 : :
590 : : /**
591 : : * g_application_command_line_get_cwd:
592 : : * @cmdline: a #GApplicationCommandLine
593 : : *
594 : : * Gets the working directory of the command line invocation.
595 : : * The string may contain non-utf8 data.
596 : : *
597 : : * It is possible that the remote application did not send a working
598 : : * directory, so this may be %NULL.
599 : : *
600 : : * The return value should not be modified or freed and is valid for as
601 : : * long as @cmdline exists.
602 : : *
603 : : * Returns: (nullable) (type filename): the current directory, or %NULL
604 : : *
605 : : * Since: 2.28
606 : : **/
607 : : const gchar *
608 : 0 : g_application_command_line_get_cwd (GApplicationCommandLine *cmdline)
609 : : {
610 : 0 : return cmdline->priv->cwd;
611 : : }
612 : :
613 : : /**
614 : : * g_application_command_line_get_environ:
615 : : * @cmdline: a #GApplicationCommandLine
616 : : *
617 : : * Gets the contents of the 'environ' variable of the command line
618 : : * invocation, as would be returned by g_get_environ(), ie as a
619 : : * %NULL-terminated list of strings in the form 'NAME=VALUE'.
620 : : * The strings may contain non-utf8 data.
621 : : *
622 : : * The remote application usually does not send an environment. Use
623 : : * %G_APPLICATION_SEND_ENVIRONMENT to affect that. Even with this flag
624 : : * set it is possible that the environment is still not available (due
625 : : * to invocation messages from other applications).
626 : : *
627 : : * The return value should not be modified or freed and is valid for as
628 : : * long as @cmdline exists.
629 : : *
630 : : * See g_application_command_line_getenv() if you are only interested
631 : : * in the value of a single environment variable.
632 : : *
633 : : * Returns: (array zero-terminated=1) (element-type filename) (transfer none):
634 : : * the environment strings, or %NULL if they were not sent
635 : : *
636 : : * Since: 2.28
637 : : **/
638 : : const gchar * const *
639 : 0 : g_application_command_line_get_environ (GApplicationCommandLine *cmdline)
640 : : {
641 : 0 : return (const gchar **)cmdline->priv->environ;
642 : : }
643 : :
644 : : /**
645 : : * g_application_command_line_getenv:
646 : : * @cmdline: a #GApplicationCommandLine
647 : : * @name: (type filename): the environment variable to get
648 : : *
649 : : * Gets the value of a particular environment variable of the command
650 : : * line invocation, as would be returned by g_getenv(). The strings may
651 : : * contain non-utf8 data.
652 : : *
653 : : * The remote application usually does not send an environment. Use
654 : : * %G_APPLICATION_SEND_ENVIRONMENT to affect that. Even with this flag
655 : : * set it is possible that the environment is still not available (due
656 : : * to invocation messages from other applications).
657 : : *
658 : : * The return value should not be modified or freed and is valid for as
659 : : * long as @cmdline exists.
660 : : *
661 : : * Returns: (nullable): the value of the variable, or %NULL if unset or unsent
662 : : *
663 : : * Since: 2.28
664 : : **/
665 : : const gchar *
666 : 0 : g_application_command_line_getenv (GApplicationCommandLine *cmdline,
667 : : const gchar *name)
668 : : {
669 : 0 : size_t length = strlen (name);
670 : : size_t i;
671 : :
672 : : /* TODO: expand on windows */
673 : 0 : if (cmdline->priv->environ)
674 : 0 : for (i = 0; cmdline->priv->environ[i]; i++)
675 : 0 : if (strncmp (cmdline->priv->environ[i], name, length) == 0 &&
676 : 0 : cmdline->priv->environ[i][length] == '=')
677 : 0 : return cmdline->priv->environ[i] + length + 1;
678 : :
679 : 0 : return NULL;
680 : : }
681 : :
682 : : /**
683 : : * g_application_command_line_get_is_remote:
684 : : * @cmdline: a #GApplicationCommandLine
685 : : *
686 : : * Determines if @cmdline represents a remote invocation.
687 : : *
688 : : * Returns: %TRUE if the invocation was remote
689 : : *
690 : : * Since: 2.28
691 : : **/
692 : : gboolean
693 : 1 : g_application_command_line_get_is_remote (GApplicationCommandLine *cmdline)
694 : : {
695 : 1 : return IS_REMOTE (cmdline);
696 : : }
697 : :
698 : : /**
699 : : * g_application_command_line_print_literal:
700 : : * @cmdline: a #GApplicationCommandLine
701 : : * @message: the message
702 : : *
703 : : * Prints a message using the stdout print handler in the invoking process.
704 : : *
705 : : * Unlike g_application_command_line_print(), @message is not a `printf()`-style
706 : : * format string. Use this function if @message contains text you don't have
707 : : * control over, that could include `printf()` escape sequences.
708 : : *
709 : : * Since: 2.80
710 : : **/
711 : : void
712 : 0 : g_application_command_line_print_literal (GApplicationCommandLine *cmdline,
713 : : const gchar *message)
714 : : {
715 : 0 : g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
716 : 0 : g_return_if_fail (message != NULL);
717 : :
718 : 0 : G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
719 : 0 : ->print_literal (cmdline, message);
720 : : }
721 : :
722 : : /**
723 : : * g_application_command_line_printerr_literal:
724 : : * @cmdline: a #GApplicationCommandLine
725 : : * @message: the message
726 : : *
727 : : * Prints a message using the stderr print handler in the invoking process.
728 : : *
729 : : * Unlike g_application_command_line_printerr(), @message is not
730 : : * a `printf()`-style format string. Use this function if @message contains text
731 : : * you don't have control over, that could include `printf()` escape sequences.
732 : : *
733 : : * Since: 2.80
734 : : **/
735 : : void
736 : 0 : g_application_command_line_printerr_literal (GApplicationCommandLine *cmdline,
737 : : const gchar *message)
738 : : {
739 : 0 : g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
740 : 0 : g_return_if_fail (message != NULL);
741 : :
742 : 0 : G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
743 : 0 : ->printerr_literal (cmdline, message);
744 : : }
745 : :
746 : : /**
747 : : * g_application_command_line_print:
748 : : * @cmdline: a #GApplicationCommandLine
749 : : * @format: a printf-style format string
750 : : * @...: arguments, as per @format
751 : : *
752 : : * Formats a message and prints it using the stdout print handler in the
753 : : * invoking process.
754 : : *
755 : : * If @cmdline is a local invocation then this is exactly equivalent to
756 : : * g_print(). If @cmdline is remote then this is equivalent to calling
757 : : * g_print() in the invoking process.
758 : : *
759 : : * Since: 2.28
760 : : **/
761 : : void
762 : 0 : g_application_command_line_print (GApplicationCommandLine *cmdline,
763 : : const gchar *format,
764 : : ...)
765 : : {
766 : : gchar *message;
767 : : va_list ap;
768 : :
769 : 0 : g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
770 : 0 : g_return_if_fail (format != NULL);
771 : :
772 : 0 : va_start (ap, format);
773 : 0 : message = g_strdup_vprintf (format, ap);
774 : 0 : va_end (ap);
775 : :
776 : 0 : G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
777 : 0 : ->print_literal (cmdline, message);
778 : 0 : g_free (message);
779 : : }
780 : :
781 : : /**
782 : : * g_application_command_line_printerr:
783 : : * @cmdline: a #GApplicationCommandLine
784 : : * @format: a printf-style format string
785 : : * @...: arguments, as per @format
786 : : *
787 : : * Formats a message and prints it using the stderr print handler in the
788 : : * invoking process.
789 : : *
790 : : * If @cmdline is a local invocation then this is exactly equivalent to
791 : : * g_printerr(). If @cmdline is remote then this is equivalent to
792 : : * calling g_printerr() in the invoking process.
793 : : *
794 : : * Since: 2.28
795 : : **/
796 : : void
797 : 0 : g_application_command_line_printerr (GApplicationCommandLine *cmdline,
798 : : const gchar *format,
799 : : ...)
800 : : {
801 : : gchar *message;
802 : : va_list ap;
803 : :
804 : 0 : g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
805 : 0 : g_return_if_fail (format != NULL);
806 : :
807 : 0 : va_start (ap, format);
808 : 0 : message = g_strdup_vprintf (format, ap);
809 : 0 : va_end (ap);
810 : :
811 : 0 : G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
812 : 0 : ->printerr_literal (cmdline, message);
813 : 0 : g_free (message);
814 : : }
815 : :
816 : : /**
817 : : * g_application_command_line_set_exit_status:
818 : : * @cmdline: a #GApplicationCommandLine
819 : : * @exit_status: the exit status
820 : : *
821 : : * Sets the exit status that will be used when the invoking process
822 : : * exits.
823 : : *
824 : : * The return value of the #GApplication::command-line signal is
825 : : * passed to this function when the handler returns. This is the usual
826 : : * way of setting the exit status.
827 : : *
828 : : * In the event that you want the remote invocation to continue running
829 : : * and want to decide on the exit status in the future, you can use this
830 : : * call. For the case of a remote invocation, the remote process will
831 : : * typically exit when the last reference is dropped on @cmdline. The
832 : : * exit status of the remote process will be equal to the last value
833 : : * that was set with this function.
834 : : *
835 : : * In the case that the commandline invocation is local, the situation
836 : : * is slightly more complicated. If the commandline invocation results
837 : : * in the mainloop running (ie: because the use-count of the application
838 : : * increased to a non-zero value) then the application is considered to
839 : : * have been 'successful' in a certain sense, and the exit status is
840 : : * always zero. If the application use count is zero, though, the exit
841 : : * status of the local #GApplicationCommandLine is used.
842 : : *
843 : : * This method is a no-op if g_application_command_line_done() has
844 : : * been called.
845 : : *
846 : : * Since: 2.28
847 : : **/
848 : : void
849 : 13 : g_application_command_line_set_exit_status (GApplicationCommandLine *cmdline,
850 : : int exit_status)
851 : : {
852 : 13 : g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
853 : :
854 : 13 : if (cmdline->priv->done)
855 : 3 : return;
856 : :
857 : 10 : cmdline->priv->exit_status = exit_status;
858 : : }
859 : :
860 : : /**
861 : : * g_application_command_line_get_exit_status:
862 : : * @cmdline: a #GApplicationCommandLine
863 : : *
864 : : * Gets the exit status of @cmdline. See
865 : : * g_application_command_line_set_exit_status() for more information.
866 : : *
867 : : * Returns: the exit status
868 : : *
869 : : * Since: 2.28
870 : : **/
871 : : int
872 : 12 : g_application_command_line_get_exit_status (GApplicationCommandLine *cmdline)
873 : : {
874 : 12 : g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), -1);
875 : :
876 : 12 : return cmdline->priv->exit_status;
877 : : }
878 : :
879 : : /**
880 : : * g_application_command_line_get_platform_data:
881 : : * @cmdline: #GApplicationCommandLine
882 : : *
883 : : * Gets the platform data associated with the invocation of @cmdline.
884 : : *
885 : : * This is a #GVariant dictionary containing information about the
886 : : * context in which the invocation occurred. It typically contains
887 : : * information like the current working directory and the startup
888 : : * notification ID.
889 : : *
890 : : * It comes from an untrusted external process and hence the types of all
891 : : * values must be validated before being used.
892 : : *
893 : : * For local invocation, it will be %NULL.
894 : : *
895 : : * Returns: (nullable) (transfer full): the platform data, or %NULL
896 : : *
897 : : * Since: 2.28
898 : : **/
899 : : GVariant *
900 : 1 : g_application_command_line_get_platform_data (GApplicationCommandLine *cmdline)
901 : : {
902 : 1 : g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
903 : :
904 : 1 : if (cmdline->priv->platform_data)
905 : 1 : return g_variant_ref (cmdline->priv->platform_data);
906 : : else
907 : 0 : return NULL;
908 : : }
909 : :
910 : : /**
911 : : * g_application_command_line_create_file_for_arg:
912 : : * @cmdline: a #GApplicationCommandLine
913 : : * @arg: (type filename): an argument from @cmdline
914 : : *
915 : : * Creates a #GFile corresponding to a filename that was given as part
916 : : * of the invocation of @cmdline.
917 : : *
918 : : * This differs from g_file_new_for_commandline_arg() in that it
919 : : * resolves relative pathnames using the current working directory of
920 : : * the invoking process rather than the local process.
921 : : *
922 : : * Returns: (transfer full): a new #GFile
923 : : *
924 : : * Since: 2.36
925 : : **/
926 : : GFile *
927 : 0 : g_application_command_line_create_file_for_arg (GApplicationCommandLine *cmdline,
928 : : const gchar *arg)
929 : : {
930 : 0 : g_return_val_if_fail (arg != NULL, NULL);
931 : :
932 : 0 : if (cmdline->priv->cwd)
933 : 0 : return g_file_new_for_commandline_arg_and_cwd (arg, cmdline->priv->cwd);
934 : :
935 : 0 : g_warning ("Requested creation of GFile for commandline invocation that did not send cwd. "
936 : : "Using cwd of local process to resolve relative path names.");
937 : :
938 : 0 : return g_file_new_for_commandline_arg (arg);
939 : : }
940 : :
941 : : /**
942 : : * g_application_command_line_done:
943 : : * @cmdline: a #GApplicationCommandLine
944 : : *
945 : : * Signals that command line processing is completed.
946 : : *
947 : : * For remote invocation, it causes the invoking process to terminate.
948 : : *
949 : : * For local invocation, it does nothing.
950 : : *
951 : : * This method should be called in the [signal@Gio.Application::command-line]
952 : : * handler, after the exit status is set and all messages are printed.
953 : : *
954 : : * After this call, g_application_command_line_set_exit_status() has no effect.
955 : : * Subsequent calls to this method are no-ops.
956 : : *
957 : : * This method is automatically called when the #GApplicationCommandLine
958 : : * object is disposed — so you can omit the call in non-garbage collected
959 : : * languages.
960 : : *
961 : : * Since: 2.80
962 : : **/
963 : : void
964 : 14 : g_application_command_line_done (GApplicationCommandLine *cmdline)
965 : : {
966 : 14 : g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
967 : :
968 : 14 : if (cmdline->priv->done)
969 : 3 : return;
970 : :
971 : 11 : G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)->done (cmdline);
972 : :
973 : 11 : cmdline->priv->done = TRUE;
974 : : }
|