[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / gio / gapplicationcommandline.c
1 /*
2  * Copyright © 2010 Codethink Limited
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * licence 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  * GApplicationCommandLineClass:
205  *
206  * The #GApplicationCommandLineClass-struct 
207  * contains private data only.
208  *
209  * Since: 2.28
210  **/
211 enum
212 {
213   PROP_NONE,
214   PROP_ARGUMENTS,
215   PROP_OPTIONS,
216   PROP_PLATFORM_DATA,
217   PROP_IS_REMOTE
218 };
219
220 struct _GApplicationCommandLinePrivate
221 {
222   GVariant *platform_data;
223   GVariant *arguments;
224   GVariant *options;
225   GVariantDict *options_dict;
226   gchar *cwd;
227
228   gchar **environ;
229   gint exit_status;
230 };
231
232 G_DEFINE_TYPE_WITH_PRIVATE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJECT)
233
234 /* All subclasses represent remote invocations of some kind. */
235 #define IS_REMOTE(cmdline) (G_TYPE_FROM_INSTANCE (cmdline) != \
236                             G_TYPE_APPLICATION_COMMAND_LINE)
237
238 static void
239 grok_platform_data (GApplicationCommandLine *cmdline)
240 {
241   GVariantIter iter;
242   const gchar *key;
243   GVariant *value;
244
245   g_variant_iter_init (&iter, cmdline->priv->platform_data);
246
247   while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
248     if (strcmp (key, "cwd") == 0)
249       {
250         if (!cmdline->priv->cwd)
251           cmdline->priv->cwd = g_variant_dup_bytestring (value, NULL);
252       }
253
254     else if (strcmp (key, "environ") == 0)
255       {
256         if (!cmdline->priv->environ)
257           cmdline->priv->environ =
258             g_variant_dup_bytestring_array (value, NULL);
259       }
260
261     else if (strcmp (key, "options") == 0)
262       {
263         if (!cmdline->priv->options)
264           cmdline->priv->options = g_variant_ref (value);
265       }
266 }
267
268 static void
269 g_application_command_line_real_print_literal (GApplicationCommandLine *cmdline,
270                                                const gchar             *message)
271 {
272   g_print ("%s", message);
273 }
274
275 static void
276 g_application_command_line_real_printerr_literal (GApplicationCommandLine *cmdline,
277                                                   const gchar             *message)
278 {
279   g_printerr ("%s", message);
280 }
281
282 static GInputStream *
283 g_application_command_line_real_get_stdin (GApplicationCommandLine *cmdline)
284 {
285 #ifdef G_OS_UNIX
286   return g_unix_input_stream_new (0, FALSE);
287 #else
288   return g_win32_input_stream_new (GetStdHandle (STD_INPUT_HANDLE), FALSE);
289 #endif
290 }
291
292 static void
293 g_application_command_line_get_property (GObject    *object,
294                                          guint       prop_id,
295                                          GValue     *value,
296                                          GParamSpec *pspec)
297 {
298   GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
299
300   switch (prop_id)
301     {
302     case PROP_ARGUMENTS:
303       g_value_set_variant (value, cmdline->priv->arguments);
304       break;
305
306     case PROP_PLATFORM_DATA:
307       g_value_set_variant (value, cmdline->priv->platform_data);
308       break;
309
310     case PROP_IS_REMOTE:
311       g_value_set_boolean (value, IS_REMOTE (cmdline));
312       break;
313
314     default:
315       g_assert_not_reached ();
316     }
317 }
318
319 static void
320 g_application_command_line_set_property (GObject      *object,
321                                          guint         prop_id,
322                                          const GValue *value,
323                                          GParamSpec   *pspec)
324 {
325   GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
326
327   switch (prop_id)
328     {
329     case PROP_ARGUMENTS:
330       g_assert (cmdline->priv->arguments == NULL);
331       cmdline->priv->arguments = g_value_dup_variant (value);
332       break;
333
334     case PROP_OPTIONS:
335       g_assert (cmdline->priv->options == NULL);
336       cmdline->priv->options = g_value_dup_variant (value);
337       break;
338
339     case PROP_PLATFORM_DATA:
340       g_assert (cmdline->priv->platform_data == NULL);
341       cmdline->priv->platform_data = g_value_dup_variant (value);
342       if (cmdline->priv->platform_data != NULL)
343         grok_platform_data (cmdline);
344       break;
345
346     default:
347       g_assert_not_reached ();
348     }
349 }
350
351 static void
352 g_application_command_line_finalize (GObject *object)
353 {
354   GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
355
356   if (cmdline->priv->options_dict)
357     g_variant_dict_unref (cmdline->priv->options_dict);
358
359   if (cmdline->priv->options)
360       g_variant_unref (cmdline->priv->options);
361
362   if (cmdline->priv->platform_data)
363     g_variant_unref (cmdline->priv->platform_data);
364   if (cmdline->priv->arguments)
365     g_variant_unref (cmdline->priv->arguments);
366
367   g_free (cmdline->priv->cwd);
368   g_strfreev (cmdline->priv->environ);
369
370   G_OBJECT_CLASS (g_application_command_line_parent_class)
371     ->finalize (object);
372 }
373
374 static void
375 g_application_command_line_init (GApplicationCommandLine *cmdline)
376 {
377   cmdline->priv = g_application_command_line_get_instance_private (cmdline);
378 }
379
380 static void
381 g_application_command_line_constructed (GObject *object)
382 {
383   GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
384
385   if (IS_REMOTE (cmdline))
386     return;
387
388   /* In the local case, set cmd and environ */
389   if (!cmdline->priv->cwd)
390     cmdline->priv->cwd = g_get_current_dir ();
391
392   if (!cmdline->priv->environ)
393     cmdline->priv->environ = g_get_environ ();
394 }
395
396 static void
397 g_application_command_line_class_init (GApplicationCommandLineClass *class)
398 {
399   GObjectClass *object_class = G_OBJECT_CLASS (class);
400
401   object_class->get_property = g_application_command_line_get_property;
402   object_class->set_property = g_application_command_line_set_property;
403   object_class->finalize = g_application_command_line_finalize;
404   object_class->constructed = g_application_command_line_constructed;
405
406   class->printerr_literal = g_application_command_line_real_printerr_literal;
407   class->print_literal = g_application_command_line_real_print_literal;
408   class->get_stdin = g_application_command_line_real_get_stdin;
409
410   g_object_class_install_property (object_class, PROP_ARGUMENTS,
411     g_param_spec_variant ("arguments",
412                           P_("Commandline arguments"),
413                           P_("The commandline that caused this ::command-line signal emission"),
414                           G_VARIANT_TYPE_BYTESTRING_ARRAY, NULL,
415                           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
416                           G_PARAM_STATIC_STRINGS));
417
418   g_object_class_install_property (object_class, PROP_OPTIONS,
419     g_param_spec_variant ("options",
420                           P_("Options"),
421                           P_("The options sent along with the commandline"),
422                           G_VARIANT_TYPE_VARDICT, NULL, G_PARAM_WRITABLE |
423                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
424
425   g_object_class_install_property (object_class, PROP_PLATFORM_DATA,
426     g_param_spec_variant ("platform-data",
427                           P_("Platform data"),
428                           P_("Platform-specific data for the commandline"),
429                           G_VARIANT_TYPE ("a{sv}"), NULL,
430                           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
431                           G_PARAM_STATIC_STRINGS));
432
433   g_object_class_install_property (object_class, PROP_IS_REMOTE,
434     g_param_spec_boolean ("is-remote",
435                           P_("Is remote"),
436                           P_("TRUE if this is a remote commandline"),
437                           FALSE,
438                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
439 }
440
441
442 /**
443  * g_application_command_line_get_arguments:
444  * @cmdline: a #GApplicationCommandLine
445  * @argc: (out) (allow-none): the length of the arguments array, or %NULL
446  *
447  * Gets the list of arguments that was passed on the command line.
448  *
449  * The strings in the array may contain non-UTF-8 data on UNIX (such as
450  * filenames or arguments given in the system locale) but are always in
451  * UTF-8 on Windows.
452  *
453  * If you wish to use the return value with #GOptionContext, you must
454  * use g_option_context_parse_strv().
455  *
456  * The return value is %NULL-terminated and should be freed using
457  * g_strfreev().
458  *
459  * Returns: (array length=argc) (transfer full): the string array
460  * containing the arguments (the argv)
461  *
462  * Since: 2.28
463  **/
464 gchar **
465 g_application_command_line_get_arguments (GApplicationCommandLine *cmdline,
466                                           int                     *argc)
467 {
468   gchar **argv;
469   gsize len;
470
471   g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
472
473   argv = g_variant_dup_bytestring_array (cmdline->priv->arguments, &len);
474
475   if (argc)
476     *argc = len;
477
478   return argv;
479 }
480
481 /**
482  * g_application_command_line_get_options_dict:
483  * @cmdline: a #GApplicationCommandLine
484  *
485  * Gets the options there were passed to g_application_command_line().
486  *
487  * If you did not override local_command_line() then these are the same
488  * options that were parsed according to the #GOptionEntrys added to the
489  * application with g_application_add_main_option_entries() and possibly
490  * modified from your GApplication::handle-local-options handler.
491  *
492  * If no options were sent then an empty dictionary is returned so that
493  * you don't need to check for %NULL.
494  *
495  * Returns: (transfer none): a #GVariantDict with the options
496  *
497  * Since: 2.40
498  **/
499 GVariantDict *
500 g_application_command_line_get_options_dict (GApplicationCommandLine *cmdline)
501 {
502   g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
503
504   if (!cmdline->priv->options_dict)
505     cmdline->priv->options_dict = g_variant_dict_new (cmdline->priv->options);
506
507   return cmdline->priv->options_dict;
508 }
509
510 /**
511  * g_application_command_line_get_stdin:
512  * @cmdline: a #GApplicationCommandLine
513  *
514  * Gets the stdin of the invoking process.
515  *
516  * The #GInputStream can be used to read data passed to the standard
517  * input of the invoking process.
518  * This doesn't work on all platforms.  Presently, it is only available
519  * on UNIX when using a DBus daemon capable of passing file descriptors.
520  * If stdin is not available then %NULL will be returned.  In the
521  * future, support may be expanded to other platforms.
522  *
523  * You must only call this function once per commandline invocation.
524  *
525  * Returns: (transfer full): a #GInputStream for stdin
526  *
527  * Since: 2.34
528  **/
529 GInputStream *
530 g_application_command_line_get_stdin (GApplicationCommandLine *cmdline)
531 {
532   return G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)->get_stdin (cmdline);
533 }
534
535 /**
536  * g_application_command_line_get_cwd:
537  * @cmdline: a #GApplicationCommandLine
538  *
539  * Gets the working directory of the command line invocation.
540  * The string may contain non-utf8 data.
541  *
542  * It is possible that the remote application did not send a working
543  * directory, so this may be %NULL.
544  *
545  * The return value should not be modified or freed and is valid for as
546  * long as @cmdline exists.
547  *
548  * Returns: the current directory, or %NULL
549  *
550  * Since: 2.28
551  **/
552 const gchar *
553 g_application_command_line_get_cwd (GApplicationCommandLine *cmdline)
554 {
555   return cmdline->priv->cwd;
556 }
557
558 /**
559  * g_application_command_line_get_environ:
560  * @cmdline: a #GApplicationCommandLine
561  *
562  * Gets the contents of the 'environ' variable of the command line
563  * invocation, as would be returned by g_get_environ(), ie as a
564  * %NULL-terminated list of strings in the form 'NAME=VALUE'.
565  * The strings may contain non-utf8 data.
566  *
567  * The remote application usually does not send an environment.  Use
568  * %G_APPLICATION_SEND_ENVIRONMENT to affect that.  Even with this flag
569  * set it is possible that the environment is still not available (due
570  * to invocation messages from other applications).
571  *
572  * The return value should not be modified or freed and is valid for as
573  * long as @cmdline exists.
574  *
575  * See g_application_command_line_getenv() if you are only interested
576  * in the value of a single environment variable.
577  *
578  * Returns: (array zero-terminated=1) (transfer none): the environment
579  * strings, or %NULL if they were not sent
580  *
581  * Since: 2.28
582  **/
583 const gchar * const *
584 g_application_command_line_get_environ (GApplicationCommandLine *cmdline)
585 {
586   return (const gchar **)cmdline->priv->environ;
587 }
588
589 /**
590  * g_application_command_line_getenv:
591  * @cmdline: a #GApplicationCommandLine
592  * @name: the environment variable to get
593  *
594  * Gets the value of a particular environment variable of the command
595  * line invocation, as would be returned by g_getenv().  The strings may
596  * contain non-utf8 data.
597  *
598  * The remote application usually does not send an environment.  Use
599  * %G_APPLICATION_SEND_ENVIRONMENT to affect that.  Even with this flag
600  * set it is possible that the environment is still not available (due
601  * to invocation messages from other applications).
602  *
603  * The return value should not be modified or freed and is valid for as
604  * long as @cmdline exists.
605  *
606  * Returns: the value of the variable, or %NULL if unset or unsent
607  *
608  * Since: 2.28
609  **/
610 const gchar *
611 g_application_command_line_getenv (GApplicationCommandLine *cmdline,
612                                    const gchar             *name)
613 {
614   gint length = strlen (name);
615   gint i;
616
617   /* TODO: expand on windows */
618   if (cmdline->priv->environ)
619     for (i = 0; cmdline->priv->environ[i]; i++)
620       if (strncmp (cmdline->priv->environ[i], name, length) == 0 &&
621           cmdline->priv->environ[i][length] == '=')
622         return cmdline->priv->environ[i] + length + 1;
623
624   return NULL;
625 }
626
627 /**
628  * g_application_command_line_get_is_remote:
629  * @cmdline: a #GApplicationCommandLine
630  *
631  * Determines if @cmdline represents a remote invocation.
632  *
633  * Returns: %TRUE if the invocation was remote
634  *
635  * Since: 2.28
636  **/
637 gboolean
638 g_application_command_line_get_is_remote (GApplicationCommandLine *cmdline)
639 {
640   return IS_REMOTE (cmdline);
641 }
642
643 /**
644  * g_application_command_line_print:
645  * @cmdline: a #GApplicationCommandLine
646  * @format: a printf-style format string
647  * @...: arguments, as per @format
648  *
649  * Formats a message and prints it using the stdout print handler in the
650  * invoking process.
651  *
652  * If @cmdline is a local invocation then this is exactly equivalent to
653  * g_print().  If @cmdline is remote then this is equivalent to calling
654  * g_print() in the invoking process.
655  *
656  * Since: 2.28
657  **/
658 void
659 g_application_command_line_print (GApplicationCommandLine *cmdline,
660                                   const gchar             *format,
661                                   ...)
662 {
663   gchar *message;
664   va_list ap;
665
666   g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
667   g_return_if_fail (format != NULL);
668
669   va_start (ap, format);
670   message = g_strdup_vprintf (format, ap);
671   va_end (ap);
672
673   G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
674     ->print_literal (cmdline, message);
675   g_free (message);
676 }
677
678 /**
679  * g_application_command_line_printerr:
680  * @cmdline: a #GApplicationCommandLine
681  * @format: a printf-style format string
682  * @...: arguments, as per @format
683  *
684  * Formats a message and prints it using the stderr print handler in the
685  * invoking process.
686  *
687  * If @cmdline is a local invocation then this is exactly equivalent to
688  * g_printerr().  If @cmdline is remote then this is equivalent to
689  * calling g_printerr() in the invoking process.
690  *
691  * Since: 2.28
692  **/
693 void
694 g_application_command_line_printerr (GApplicationCommandLine *cmdline,
695                                      const gchar             *format,
696                                      ...)
697 {
698   gchar *message;
699   va_list ap;
700
701   g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
702   g_return_if_fail (format != NULL);
703
704   va_start (ap, format);
705   message = g_strdup_vprintf (format, ap);
706   va_end (ap);
707
708   G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
709     ->printerr_literal (cmdline, message);
710   g_free (message);
711 }
712
713 /**
714  * g_application_command_line_set_exit_status:
715  * @cmdline: a #GApplicationCommandLine
716  * @exit_status: the exit status
717  *
718  * Sets the exit status that will be used when the invoking process
719  * exits.
720  *
721  * The return value of the #GApplication::command-line signal is
722  * passed to this function when the handler returns.  This is the usual
723  * way of setting the exit status.
724  *
725  * In the event that you want the remote invocation to continue running
726  * and want to decide on the exit status in the future, you can use this
727  * call.  For the case of a remote invocation, the remote process will
728  * typically exit when the last reference is dropped on @cmdline.  The
729  * exit status of the remote process will be equal to the last value
730  * that was set with this function.
731  *
732  * In the case that the commandline invocation is local, the situation
733  * is slightly more complicated.  If the commandline invocation results
734  * in the mainloop running (ie: because the use-count of the application
735  * increased to a non-zero value) then the application is considered to
736  * have been 'successful' in a certain sense, and the exit status is
737  * always zero.  If the application use count is zero, though, the exit
738  * status of the local #GApplicationCommandLine is used.
739  *
740  * Since: 2.28
741  **/
742 void
743 g_application_command_line_set_exit_status (GApplicationCommandLine *cmdline,
744                                             int                      exit_status)
745 {
746   g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
747
748   cmdline->priv->exit_status = exit_status;
749 }
750
751 /**
752  * g_application_command_line_get_exit_status:
753  * @cmdline: a #GApplicationCommandLine
754  *
755  * Gets the exit status of @cmdline.  See
756  * g_application_command_line_set_exit_status() for more information.
757  *
758  * Returns: the exit status
759  *
760  * Since: 2.28
761  **/
762 int
763 g_application_command_line_get_exit_status (GApplicationCommandLine *cmdline)
764 {
765   g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), -1);
766
767   return cmdline->priv->exit_status;
768 }
769
770 /**
771  * g_application_command_line_get_platform_data:
772  * @cmdline: #GApplicationCommandLine
773  *
774  * Gets the platform data associated with the invocation of @cmdline.
775  *
776  * This is a #GVariant dictionary containing information about the
777  * context in which the invocation occurred.  It typically contains
778  * information like the current working directory and the startup
779  * notification ID.
780  *
781  * For local invocation, it will be %NULL.
782  *
783  * Returns: (nullable): the platform data, or %NULL
784  *
785  * Since: 2.28
786  **/
787 GVariant *
788 g_application_command_line_get_platform_data (GApplicationCommandLine *cmdline)
789 {
790   g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
791
792   if (cmdline->priv->platform_data)
793     return g_variant_ref (cmdline->priv->platform_data);
794   else
795       return NULL;
796 }
797
798 /**
799  * g_application_command_line_create_file_for_arg:
800  * @cmdline: a #GApplicationCommandLine
801  * @arg: an argument from @cmdline
802  *
803  * Creates a #GFile corresponding to a filename that was given as part
804  * of the invocation of @cmdline.
805  *
806  * This differs from g_file_new_for_commandline_arg() in that it
807  * resolves relative pathnames using the current working directory of
808  * the invoking process rather than the local process.
809  *
810  * Returns: (transfer full): a new #GFile
811  *
812  * Since: 2.36
813  **/
814 GFile *
815 g_application_command_line_create_file_for_arg (GApplicationCommandLine *cmdline,
816                                                 const gchar             *arg)
817 {
818   g_return_val_if_fail (arg != NULL, NULL);
819
820   if (cmdline->priv->cwd)
821     return g_file_new_for_commandline_arg_and_cwd (arg, cmdline->priv->cwd);
822
823   g_warning ("Requested creation of GFile for commandline invocation that did not send cwd. "
824              "Using cwd of local process to resolve relative path names.");
825
826   return g_file_new_for_commandline_arg (arg);
827 }