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