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