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 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 grok_platform_data (GApplicationCommandLine *cmdline)
253 {
254 GVariantIter iter;
255 const gchar *key;
256 GVariant *value;
257
258 g_variant_iter_init (&iter, cmdline->priv->platform_data);
259
260 while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
261 if (strcmp (key, "cwd") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING))
262 {
263 if (!cmdline->priv->cwd)
264 cmdline->priv->cwd = g_variant_dup_bytestring (value, NULL);
265 }
266
267 else if (strcmp (key, "environ") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING_ARRAY))
268 {
269 if (!cmdline->priv->environ)
270 cmdline->priv->environ =
271 g_variant_dup_bytestring_array (value, NULL);
272 }
273
274 else if (strcmp (key, "options") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_VARDICT))
275 {
276 if (!cmdline->priv->options)
277 cmdline->priv->options = g_variant_ref (value);
278 }
279 }
280
281 static void
282 g_application_command_line_real_print_literal (GApplicationCommandLine *cmdline,
283 const gchar *message)
284 {
285 g_print ("%s", message);
286 }
287
288 static void
289 g_application_command_line_real_printerr_literal (GApplicationCommandLine *cmdline,
290 const gchar *message)
291 {
292 g_printerr ("%s", message);
293 }
294
295 static GInputStream *
296 g_application_command_line_real_get_stdin (GApplicationCommandLine *cmdline)
297 {
298 #ifdef G_OS_UNIX
299 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 g_application_command_line_real_done (GApplicationCommandLine *cmdline)
307 {
308 }
309
310 static void
311 g_application_command_line_get_property (GObject *object,
312 guint prop_id,
313 GValue *value,
314 GParamSpec *pspec)
315 {
316 GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
317
318 switch (prop_id)
319 {
320 case PROP_ARGUMENTS:
321 g_value_set_variant (value, cmdline->priv->arguments);
322 break;
323
324 case PROP_PLATFORM_DATA:
325 g_value_set_variant (value, cmdline->priv->platform_data);
326 break;
327
328 case PROP_IS_REMOTE:
329 g_value_set_boolean (value, IS_REMOTE (cmdline));
330 break;
331
332 default:
333 g_assert_not_reached ();
334 }
335 }
336
337 static void
338 g_application_command_line_set_property (GObject *object,
339 guint prop_id,
340 const GValue *value,
341 GParamSpec *pspec)
342 {
343 GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
344
345 switch (prop_id)
346 {
347 case PROP_ARGUMENTS:
348 g_assert (cmdline->priv->arguments == NULL);
349 cmdline->priv->arguments = g_value_dup_variant (value);
350 break;
351
352 case PROP_OPTIONS:
353 g_assert (cmdline->priv->options == NULL);
354 cmdline->priv->options = g_value_dup_variant (value);
355 break;
356
357 case PROP_PLATFORM_DATA:
358 g_assert (cmdline->priv->platform_data == NULL);
359 cmdline->priv->platform_data = g_value_dup_variant (value);
360 if (cmdline->priv->platform_data != NULL)
361 grok_platform_data (cmdline);
362 break;
363
364 default:
365 g_assert_not_reached ();
366 }
367 }
368
369 static void
370 g_application_command_line_dispose (GObject *object)
371 {
372 GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
373
374 g_application_command_line_done (cmdline);
375
376 G_OBJECT_CLASS (g_application_command_line_parent_class)->dispose (object);
377 }
378
379 static void
380 g_application_command_line_finalize (GObject *object)
381 {
382 GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
383
384 if (cmdline->priv->options_dict)
385 g_variant_dict_unref (cmdline->priv->options_dict);
386
387 if (cmdline->priv->options)
388 g_variant_unref (cmdline->priv->options);
389
390 if (cmdline->priv->platform_data)
391 g_variant_unref (cmdline->priv->platform_data);
392 if (cmdline->priv->arguments)
393 g_variant_unref (cmdline->priv->arguments);
394
395 g_free (cmdline->priv->cwd);
396 g_strfreev (cmdline->priv->environ);
397
398 G_OBJECT_CLASS (g_application_command_line_parent_class)
399 ->finalize (object);
400 }
401
402 static void
403 g_application_command_line_init (GApplicationCommandLine *cmdline)
404 {
405 cmdline->priv = g_application_command_line_get_instance_private (cmdline);
406 }
407
408 static void
409 g_application_command_line_constructed (GObject *object)
410 {
411 GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
412
413 if (IS_REMOTE (cmdline))
414 return;
415
416 /* In the local case, set cmd and environ */
417 if (!cmdline->priv->cwd)
418 cmdline->priv->cwd = g_get_current_dir ();
419
420 if (!cmdline->priv->environ)
421 cmdline->priv->environ = g_get_environ ();
422 }
423
424 static void
425 g_application_command_line_class_init (GApplicationCommandLineClass *class)
426 {
427 GObjectClass *object_class = G_OBJECT_CLASS (class);
428
429 object_class->get_property = g_application_command_line_get_property;
430 object_class->set_property = g_application_command_line_set_property;
431 object_class->finalize = g_application_command_line_finalize;
432 object_class->dispose = g_application_command_line_dispose;
433 object_class->constructed = g_application_command_line_constructed;
434
435 class->printerr_literal = g_application_command_line_real_printerr_literal;
436 class->print_literal = g_application_command_line_real_print_literal;
437 class->get_stdin = g_application_command_line_real_get_stdin;
438
439 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 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 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 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 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 }
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 g_application_command_line_get_arguments (GApplicationCommandLine *cmdline,
518 int *argc)
519 {
520 gchar **argv;
521 gsize len;
522
523 g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
524
525 argv = g_variant_dup_bytestring_array (cmdline->priv->arguments, &len);
526
527 if (argc)
528 *argc = len;
529
530 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 g_application_command_line_get_options_dict (GApplicationCommandLine *cmdline)
556 {
557 g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
558
559 if (!cmdline->priv->options_dict)
560 cmdline->priv->options_dict = g_variant_dict_new (cmdline->priv->options);
561
562 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 g_application_command_line_get_stdin (GApplicationCommandLine *cmdline)
586 {
587 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 g_application_command_line_get_cwd (GApplicationCommandLine *cmdline)
609 {
610 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 g_application_command_line_get_environ (GApplicationCommandLine *cmdline)
640 {
641 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 g_application_command_line_getenv (GApplicationCommandLine *cmdline,
667 const gchar *name)
668 {
669 gint length = strlen (name);
670 gint i;
671
672 /* TODO: expand on windows */
673 if (cmdline->priv->environ)
674 for (i = 0; cmdline->priv->environ[i]; i++)
675 if (strncmp (cmdline->priv->environ[i], name, length) == 0 &&
676 cmdline->priv->environ[i][length] == '=')
677 return cmdline->priv->environ[i] + length + 1;
678
679 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 g_application_command_line_get_is_remote (GApplicationCommandLine *cmdline)
694 {
695 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 g_application_command_line_print_literal (GApplicationCommandLine *cmdline,
713 const gchar *message)
714 {
715 g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
716 g_return_if_fail (message != NULL);
717
718 G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
719 ->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 g_application_command_line_printerr_literal (GApplicationCommandLine *cmdline,
737 const gchar *message)
738 {
739 g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
740 g_return_if_fail (message != NULL);
741
742 G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
743 ->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 g_application_command_line_print (GApplicationCommandLine *cmdline,
763 const gchar *format,
764 ...)
765 {
766 gchar *message;
767 va_list ap;
768
769 g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
770 g_return_if_fail (format != NULL);
771
772 va_start (ap, format);
773 message = g_strdup_vprintf (format, ap);
774 va_end (ap);
775
776 G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
777 ->print_literal (cmdline, message);
778 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 g_application_command_line_printerr (GApplicationCommandLine *cmdline,
798 const gchar *format,
799 ...)
800 {
801 gchar *message;
802 va_list ap;
803
804 g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
805 g_return_if_fail (format != NULL);
806
807 va_start (ap, format);
808 message = g_strdup_vprintf (format, ap);
809 va_end (ap);
810
811 G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
812 ->printerr_literal (cmdline, message);
813 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 g_application_command_line_set_exit_status (GApplicationCommandLine *cmdline,
850 int exit_status)
851 {
852 g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
853
854 if (cmdline->priv->done)
855 return;
856
857 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 g_application_command_line_get_exit_status (GApplicationCommandLine *cmdline)
873 {
874 g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), -1);
875
876 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 g_application_command_line_get_platform_data (GApplicationCommandLine *cmdline)
901 {
902 g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
903
904 if (cmdline->priv->platform_data)
905 return g_variant_ref (cmdline->priv->platform_data);
906 else
907 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 g_application_command_line_create_file_for_arg (GApplicationCommandLine *cmdline,
928 const gchar *arg)
929 {
930 g_return_val_if_fail (arg != NULL, NULL);
931
932 if (cmdline->priv->cwd)
933 return g_file_new_for_commandline_arg_and_cwd (arg, cmdline->priv->cwd);
934
935 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 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 g_application_command_line_done (GApplicationCommandLine *cmdline)
965 {
966 g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
967
968 if (cmdline->priv->done)
969 return;
970
971 G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)->done (cmdline);
972
973 cmdline->priv->done = TRUE;
974 }