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