X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgapplicationcommandline.c;h=d5e508a863f8ddf4d6af35d9b5deebf303ffb1f6;hb=e55a953642a9e402f4363f9fa347b6061dd78990;hp=e7a5c6c694e044a2ff1e0626bcdee978518dd3fe;hpb=1b28408b8bfe282f671716a39bba3208d3fef39a;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gapplicationcommandline.c b/gio/gapplicationcommandline.c index e7a5c6c..d5e508a 100644 --- a/gio/gapplicationcommandline.c +++ b/gio/gapplicationcommandline.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, - * USA. + * License along with this library; if not, see . * * Authors: Ryan Lortie */ @@ -24,16 +22,26 @@ #include "gapplicationcommandline.h" #include "glibintl.h" +#include "gfile.h" #include #include -G_DEFINE_TYPE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJECT) +#ifdef G_OS_UNIX +#include "gunixinputstream.h" +#endif + +#ifdef G_OS_WIN32 +#include +#undef environ +#include "gwin32inputstream.h" +#endif /** * SECTION:gapplicationcommandline * @title: GApplicationCommandLine * @short_description: A command-line invocation of an application + * @include: gio/gio.h * @see_also: #GApplication * * #GApplicationCommandLine represents a command-line invocation of @@ -49,7 +57,8 @@ G_DEFINE_TYPE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJEC * The GApplicationCommandLine object can provide the @argc and @argv * parameters for use with the #GOptionContext command-line parsing API, * with the g_application_command_line_get_arguments() function. See - * for an example. + * [gapplication-example-cmdline3.c][gapplication-example-cmdline3] + * for an example. * * The exit status of the originally-invoked process may be set and * messages can be printed to stdout or stderr of that process. The @@ -57,72 +66,153 @@ G_DEFINE_TYPE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJEC * of this object (ie: the process exits when the last reference is * dropped). * - * The main use for #GApplicationCommandline (and the + * The main use for #GApplicationCommandLine (and the * #GApplication::command-line signal) is 'Emacs server' like use cases: - * You can set the EDITOR environment variable to have - * e.g. git use your favourite editor to edit commit messages, and if you - * already have an instance of the editor running, the editing will happen + * You can set the `EDITOR` environment variable to have e.g. git use + * your favourite editor to edit commit messages, and if you already + * have an instance of the editor running, the editing will happen * in the running instance, instead of opening a new one. An important * aspect of this use case is that the process that gets started by git * does not return until the editing is done. * - * Handling commandline arguments with GApplication - * - * A simple example where the commandline is completely handled - * in the #GApplication::command-line handler. The launching instance exits - * once the signal handler in the primary instance has returned, and the - * return value of the signal handler becomes the exit status of the launching - * instance. - * - * - * - * FIXME: MISSING XINCLUDE CONTENT - * - * - * - * - * Split commandline handling - * - * An example of split commandline handling. Options that start with - * --local- are handled locally, all other options are - * passed to the #GApplication::command-line handler which runs in the primary + * Normally, the commandline is completely handled in the + * #GApplication::command-line handler. The launching instance exits + * once the signal handler in the primary instance has returned, and + * the return value of the signal handler becomes the exit status + * of the launching instance. + * |[ + * static int + * command_line (GApplication *application, + * GApplicationCommandLine *cmdline) + * { + * gchar **argv; + * gint argc; + * gint i; + * + * argv = g_application_command_line_get_arguments (cmdline, &argc); + * + * g_application_command_line_print (cmdline, + * "This text is written back\n" + * "to stdout of the caller\n"); + * + * for (i = 0; i < argc; i++) + * g_print ("argument %d: %s\n", i, argv[i]); + * + * g_strfreev (argv); + * + * return 0; + * } + * ]| + * The complete example can be found here: + * [gapplication-example-cmdline.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline.c) + * + * In more complicated cases, the handling of the comandline can be + * split between the launcher and the primary instance. + * |[ + * static gboolean + * test_local_cmdline (GApplication *application, + * gchar ***arguments, + * gint *exit_status) + * { + * gint i, j; + * gchar **argv; + * + * argv = *arguments; + * + * i = 1; + * while (argv[i]) + * { + * if (g_str_has_prefix (argv[i], "--local-")) + * { + * g_print ("handling argument %s locally\n", argv[i]); + * g_free (argv[i]); + * for (j = i; argv[j]; j++) + * argv[j] = argv[j + 1]; + * } + * else + * { + * g_print ("not handling argument %s locally\n", argv[i]); + * i++; + * } + * } + * + * *exit_status = 0; + * + * return FALSE; + * } + * + * static void + * test_application_class_init (TestApplicationClass *class) + * { + * G_APPLICATION_CLASS (class)->local_command_line = test_local_cmdline; + * + * ... + * } + * ]| + * In this example of split commandline handling, options that start + * with `--local-` are handled locally, all other options are passed + * to the #GApplication::command-line handler which runs in the primary * instance. - * - * - * - * FIXME: MISSING XINCLUDE CONTENT - * - * - * - * - * Deferred commandline handling - * - * An example of deferred commandline handling. Here, the commandline is - * not completely handled before the #GApplication::command-line handler - * returns. Instead, we keep a reference to the GApplicationCommandline - * object and handle it later(in this example, in an idle). Note that it - * is necessary to hold the application until you are done with the - * commandline. - * - * - * This example also shows how to use #GOptionContext for parsing the - * commandline arguments. Note that it is necessary to disable the - * built-in help-handling of #GOptionContext, since it calls exit() - * after printing help, which is not what you want to happen in - * the primary instance. - * - * - * - * FIXME: MISSING XINCLUDE CONTENT - * - * - * - **/ + * + * The complete example can be found here: + * [gapplication-example-cmdline2.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline2.c) + * + * If handling the commandline requires a lot of work, it may + * be better to defer it. + * |[ + * static gboolean + * my_cmdline_handler (gpointer data) + * { + * GApplicationCommandLine *cmdline = data; + * + * // do the heavy lifting in an idle + * + * g_application_command_line_set_exit_status (cmdline, 0); + * g_object_unref (cmdline); // this releases the application + * + * return G_SOURCE_REMOVE; + * } + * + * static int + * command_line (GApplication *application, + * GApplicationCommandLine *cmdline) + * { + * // keep the application running until we are done with this commandline + * g_application_hold (application); + * + * g_object_set_data_full (G_OBJECT (cmdline), + * "application", application, + * (GDestroyNotify)g_application_release); + * + * g_object_ref (cmdline); + * g_idle_add (my_cmdline_handler, cmdline); + * + * return 0; + * } + * ]| + * In this example the commandline is not completely handled before + * the #GApplication::command-line handler returns. Instead, we keep + * a reference to the #GApplicationCommandLine object and handle it + * later (in this example, in an idle). Note that it is necessary to + * hold the application until you are done with the commandline. + * + * The complete example can be found here: + * [gapplication-example-cmdline3.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline3.c) + */ +/** + * GApplicationCommandLineClass: + * + * The #GApplicationCommandLineClass-struct + * contains private data only. + * + * Since: 2.28 + **/ enum { PROP_NONE, PROP_ARGUMENTS, + PROP_OPTIONS, PROP_PLATFORM_DATA, PROP_IS_REMOTE }; @@ -131,12 +221,16 @@ struct _GApplicationCommandLinePrivate { GVariant *platform_data; GVariant *arguments; - GVariant *cwd; + GVariant *options; + GVariantDict *options_dict; + gchar *cwd; - const gchar **environ; + gchar **environ; gint exit_status; }; +G_DEFINE_TYPE_WITH_PRIVATE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJECT) + /* All subclasses represent remote invocations of some kind. */ #define IS_REMOTE(cmdline) (G_TYPE_FROM_INSTANCE (cmdline) != \ G_TYPE_APPLICATION_COMMAND_LINE) @@ -154,14 +248,20 @@ grok_platform_data (GApplicationCommandLine *cmdline) if (strcmp (key, "cwd") == 0) { if (!cmdline->priv->cwd) - cmdline->priv->cwd = g_variant_ref (value); + cmdline->priv->cwd = g_variant_dup_bytestring (value, NULL); } else if (strcmp (key, "environ") == 0) { if (!cmdline->priv->environ) cmdline->priv->environ = - g_variant_get_bytestring_array (value, NULL); + g_variant_dup_bytestring_array (value, NULL); + } + + else if (strcmp (key, "options") == 0) + { + if (!cmdline->priv->options) + cmdline->priv->options = g_variant_ref (value); } } @@ -169,14 +269,24 @@ static void g_application_command_line_real_print_literal (GApplicationCommandLine *cmdline, const gchar *message) { - g_print ("%s\n", message); + g_print ("%s", message); } static void g_application_command_line_real_printerr_literal (GApplicationCommandLine *cmdline, const gchar *message) { - g_printerr ("%s\n", message); + g_printerr ("%s", message); +} + +static GInputStream * +g_application_command_line_real_get_stdin (GApplicationCommandLine *cmdline) +{ +#ifdef G_OS_UNIX + return g_unix_input_stream_new (0, FALSE); +#else + return g_win32_input_stream_new (GetStdHandle (STD_INPUT_HANDLE), FALSE); +#endif } static void @@ -221,6 +331,11 @@ g_application_command_line_set_property (GObject *object, cmdline->priv->arguments = g_value_dup_variant (value); break; + case PROP_OPTIONS: + g_assert (cmdline->priv->options == NULL); + cmdline->priv->options = g_value_dup_variant (value); + break; + case PROP_PLATFORM_DATA: g_assert (cmdline->priv->platform_data == NULL); cmdline->priv->platform_data = g_value_dup_variant (value); @@ -238,12 +353,19 @@ g_application_command_line_finalize (GObject *object) { GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); + if (cmdline->priv->options_dict) + g_variant_dict_unref (cmdline->priv->options_dict); + + if (cmdline->priv->options) + g_variant_unref (cmdline->priv->options); + if (cmdline->priv->platform_data) g_variant_unref (cmdline->priv->platform_data); if (cmdline->priv->arguments) g_variant_unref (cmdline->priv->arguments); - if (cmdline->priv->cwd) - g_variant_unref (cmdline->priv->cwd); + + g_free (cmdline->priv->cwd); + g_strfreev (cmdline->priv->environ); G_OBJECT_CLASS (g_application_command_line_parent_class) ->finalize (object); @@ -252,10 +374,23 @@ g_application_command_line_finalize (GObject *object) static void g_application_command_line_init (GApplicationCommandLine *cmdline) { - cmdline->priv = - G_TYPE_INSTANCE_GET_PRIVATE (cmdline, - G_TYPE_APPLICATION_COMMAND_LINE, - GApplicationCommandLinePrivate); + cmdline->priv = g_application_command_line_get_instance_private (cmdline); +} + +static void +g_application_command_line_constructed (GObject *object) +{ + GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); + + if (IS_REMOTE (cmdline)) + return; + + /* In the local case, set cmd and environ */ + if (!cmdline->priv->cwd) + cmdline->priv->cwd = g_get_current_dir (); + + if (!cmdline->priv->environ) + cmdline->priv->environ = g_get_environ (); } static void @@ -266,8 +401,11 @@ g_application_command_line_class_init (GApplicationCommandLineClass *class) object_class->get_property = g_application_command_line_get_property; object_class->set_property = g_application_command_line_set_property; object_class->finalize = g_application_command_line_finalize; + object_class->constructed = g_application_command_line_constructed; + class->printerr_literal = g_application_command_line_real_printerr_literal; class->print_literal = g_application_command_line_real_print_literal; + class->get_stdin = g_application_command_line_real_get_stdin; g_object_class_install_property (object_class, PROP_ARGUMENTS, g_param_spec_variant ("arguments", @@ -277,6 +415,13 @@ g_application_command_line_class_init (GApplicationCommandLineClass *class) G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_OPTIONS, + g_param_spec_variant ("options", + P_("Options"), + P_("The options sent along with the commandline"), + G_VARIANT_TYPE_VARDICT, NULL, G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_PLATFORM_DATA, g_param_spec_variant ("platform-data", P_("Platform data"), @@ -291,19 +436,22 @@ g_application_command_line_class_init (GApplicationCommandLineClass *class) P_("TRUE if this is a remote commandline"), FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_type_class_add_private (class, sizeof (GApplicationCommandLinePrivate)); } /** * g_application_command_line_get_arguments: * @cmdline: a #GApplicationCommandLine - * @argc: (out): the length of the arguments array, or %NULL + * @argc: (out) (allow-none): the length of the arguments array, or %NULL * * Gets the list of arguments that was passed on the command line. * - * The strings in the array may contain non-utf8 data. + * The strings in the array may contain non-UTF-8 data on UNIX (such as + * filenames or arguments given in the system locale) but are always in + * UTF-8 on Windows. + * + * If you wish to use the return value with #GOptionContext, you must + * use g_option_context_parse_strv(). * * The return value is %NULL-terminated and should be freed using * g_strfreev(). @@ -331,6 +479,60 @@ g_application_command_line_get_arguments (GApplicationCommandLine *cmdline, } /** + * g_application_command_line_get_options_dict: + * @cmdline: a #GApplicationCommandLine + * + * Gets the options there were passed to g_application_command_line(). + * + * If you did not override local_command_line() then these are the same + * options that were parsed according to the #GOptionEntrys added to the + * application with g_application_add_main_option_entries() and possibly + * modified from your GApplication::handle-local-options handler. + * + * If no options were sent then an empty dictionary is returned so that + * you don't need to check for %NULL. + * + * Returns: (transfer none): a #GVariantDict with the options + * + * Since: 2.40 + **/ +GVariantDict * +g_application_command_line_get_options_dict (GApplicationCommandLine *cmdline) +{ + g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL); + + if (!cmdline->priv->options_dict) + cmdline->priv->options_dict = g_variant_dict_new (cmdline->priv->options); + + return cmdline->priv->options_dict; +} + +/** + * g_application_command_line_get_stdin: + * @cmdline: a #GApplicationCommandLine + * + * Gets the stdin of the invoking process. + * + * The #GInputStream can be used to read data passed to the standard + * input of the invoking process. + * This doesn't work on all platforms. Presently, it is only available + * on UNIX when using a DBus daemon capable of passing file descriptors. + * If stdin is not available then %NULL will be returned. In the + * future, support may be expanded to other platforms. + * + * You must only call this function once per commandline invocation. + * + * Returns: (transfer full): a #GInputStream for stdin + * + * Since: 2.34 + **/ +GInputStream * +g_application_command_line_get_stdin (GApplicationCommandLine *cmdline) +{ + return G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)->get_stdin (cmdline); +} + +/** * g_application_command_line_get_cwd: * @cmdline: a #GApplicationCommandLine * @@ -350,10 +552,7 @@ g_application_command_line_get_arguments (GApplicationCommandLine *cmdline, const gchar * g_application_command_line_get_cwd (GApplicationCommandLine *cmdline) { - if (cmdline->priv->cwd) - return g_variant_get_bytestring (cmdline->priv->cwd); - else - return NULL; + return cmdline->priv->cwd; } /** @@ -384,7 +583,7 @@ g_application_command_line_get_cwd (GApplicationCommandLine *cmdline) const gchar * const * g_application_command_line_get_environ (GApplicationCommandLine *cmdline) { - return cmdline->priv->environ; + return (const gchar **)cmdline->priv->environ; } /** @@ -581,7 +780,7 @@ g_application_command_line_get_exit_status (GApplicationCommandLine *cmdline) * * For local invocation, it will be %NULL. * - * Returns: the platform data, or %NULL + * Returns: (nullable): the platform data, or %NULL * * Since: 2.28 **/ @@ -595,3 +794,34 @@ g_application_command_line_get_platform_data (GApplicationCommandLine *cmdline) else return NULL; } + +/** + * g_application_command_line_create_file_for_arg: + * @cmdline: a #GApplicationCommandLine + * @arg: an argument from @cmdline + * + * Creates a #GFile corresponding to a filename that was given as part + * of the invocation of @cmdline. + * + * This differs from g_file_new_for_commandline_arg() in that it + * resolves relative pathnames using the current working directory of + * the invoking process rather than the local process. + * + * Returns: (transfer full): a new #GFile + * + * Since: 2.36 + **/ +GFile * +g_application_command_line_create_file_for_arg (GApplicationCommandLine *cmdline, + const gchar *arg) +{ + g_return_val_if_fail (arg != NULL, NULL); + + if (cmdline->priv->cwd) + return g_file_new_for_commandline_arg_and_cwd (arg, cmdline->priv->cwd); + + g_warning ("Requested creation of GFile for commandline invocation that did not send cwd. " + "Using cwd of local process to resolve relative path names."); + + return g_file_new_for_commandline_arg (arg); +}