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