Various documentation fixes
[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, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
17  * USA.
18  *
19  * Authors: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 #include "config.h"
23
24 #include "gapplicationcommandline.h"
25
26 #include "glibintl.h"
27
28 #include <string.h>
29 #include <stdio.h>
30
31 G_DEFINE_TYPE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJECT)
32
33 /**
34  * SECTION:gapplicationcommandline
35  * @title: GApplicationCommandLine
36  * @short_description: A class representing a command-line invocation of
37  *                     an application
38  * @see_also: #GApplication
39  *
40  * #GApplicationCommandLine represents a command-line invocation of
41  * an application.  It is created by #GApplication and emitted
42  * in the #GApplication::command-line signal and virtual function.
43  *
44  * The class contains the list of arguments that the program was invoked
45  * with.  It is also possible to query if the commandline invocation was
46  * local (ie: the current process is running in direct response to the
47  * invocation) or remote (ie: some other process forwarded the
48  * commandline to this process).
49  *
50  * The exit status of the originally-invoked process may be set and
51  * messages can be printed to stdout or stderr of that process.  The
52  * lifecycle of the originally-invoked process is tied to the lifecycle
53  * of this object (ie: the process exits when the last reference is
54  * dropped).
55  *
56  * <example id="gapplication-example-cmdline"><title>Handling commandline arguments with GApplication</title>
57  * <programlisting>
58  * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gapplication-example-cmdline.c">
59  *   <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
60  * </xi:include>
61  * </programlisting>
62  * </example>
63  *
64  * <example id="gapplication-example-cmdline2"><title>Complicated commandline handling</title>
65  * <programlisting>
66  * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gapplication-example-cmdline2.c">
67  *   <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
68  * </xi:include>
69  * </programlisting>
70  * </example>
71  **/
72
73 enum
74 {
75   PROP_NONE,
76   PROP_ARGUMENTS,
77   PROP_PLATFORM_DATA,
78   PROP_IS_REMOTE
79 };
80
81 struct _GApplicationCommandLinePrivate
82 {
83   GVariant *platform_data;
84   GVariant *arguments;
85   GVariant *cwd;
86
87   const gchar **environ;
88   gint exit_status;
89 };
90
91 /* All subclasses represent remote invocations of some kind. */
92 #define IS_REMOTE(cmdline) (G_TYPE_FROM_INSTANCE (cmdline) != \
93                             G_TYPE_APPLICATION_COMMAND_LINE)
94
95 static void
96 grok_platform_data (GApplicationCommandLine *cmdline)
97 {
98   GVariantIter iter;
99   const gchar *key;
100   GVariant *value;
101
102   g_variant_iter_init (&iter, cmdline->priv->platform_data);
103
104   while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
105     if (strcmp (key, "cwd") == 0)
106       {
107         if (!cmdline->priv->cwd)
108           cmdline->priv->cwd = g_variant_ref (value);
109       }
110
111     else if (strcmp (key, "environ") == 0)
112       {
113         if (!cmdline->priv->environ)
114           cmdline->priv->environ =
115             g_variant_get_bytestring_array (value, NULL);
116       }
117 }
118
119 static void
120 g_application_command_line_real_print_literal (GApplicationCommandLine *cmdline,
121                                                const gchar             *message)
122 {
123   g_print ("%s\n", message);
124 }
125
126 static void
127 g_application_command_line_real_printerr_literal (GApplicationCommandLine *cmdline,
128                                                   const gchar             *message)
129 {
130   g_printerr ("%s\n", message);
131 }
132
133 static void
134 g_application_command_line_get_property (GObject    *object,
135                                          guint       prop_id,
136                                          GValue     *value,
137                                          GParamSpec *pspec)
138 {
139   GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
140
141   switch (prop_id)
142     {
143     case PROP_ARGUMENTS:
144       g_value_set_variant (value, cmdline->priv->arguments);
145       break;
146
147     case PROP_PLATFORM_DATA:
148       g_value_set_variant (value, cmdline->priv->platform_data);
149       break;
150
151     case PROP_IS_REMOTE:
152       g_value_set_boolean (value, IS_REMOTE (cmdline));
153       break;
154
155     default:
156       g_assert_not_reached ();
157     }
158 }
159
160 static void
161 g_application_command_line_set_property (GObject      *object,
162                                          guint         prop_id,
163                                          const GValue *value,
164                                          GParamSpec   *pspec)
165 {
166   GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
167
168   switch (prop_id)
169     {
170     case PROP_ARGUMENTS:
171       g_assert (cmdline->priv->arguments == NULL);
172       cmdline->priv->arguments = g_value_dup_variant (value);
173       break;
174
175     case PROP_PLATFORM_DATA:
176       g_assert (cmdline->priv->platform_data == NULL);
177       cmdline->priv->platform_data = g_value_dup_variant (value);
178       if (cmdline->priv->platform_data != NULL)
179         grok_platform_data (cmdline);
180       break;
181
182     default:
183       g_assert_not_reached ();
184     }
185 }
186
187 static void
188 g_application_command_line_finalize (GObject *object)
189 {
190   GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);
191
192   if (cmdline->priv->platform_data)
193     g_variant_unref (cmdline->priv->platform_data);
194   if (cmdline->priv->arguments)
195     g_variant_unref (cmdline->priv->arguments);
196   if (cmdline->priv->cwd)
197     g_variant_unref (cmdline->priv->cwd);
198
199   G_OBJECT_CLASS (g_application_command_line_parent_class)
200     ->finalize (object);
201 }
202
203 static void
204 g_application_command_line_init (GApplicationCommandLine *cmdline)
205 {
206   cmdline->priv =
207     G_TYPE_INSTANCE_GET_PRIVATE (cmdline,
208                                  G_TYPE_APPLICATION_COMMAND_LINE,
209                                  GApplicationCommandLinePrivate);
210 }
211
212 static void
213 g_application_command_line_class_init (GApplicationCommandLineClass *class)
214 {
215   GObjectClass *object_class = G_OBJECT_CLASS (class);
216
217   object_class->get_property = g_application_command_line_get_property;
218   object_class->set_property = g_application_command_line_set_property;
219   object_class->finalize = g_application_command_line_finalize;
220   class->printerr_literal = g_application_command_line_real_printerr_literal;
221   class->print_literal = g_application_command_line_real_print_literal;
222
223   g_object_class_install_property (object_class, PROP_ARGUMENTS,
224     g_param_spec_variant ("arguments",
225                           P_("Commandline arguments"),
226                           P_("The commandline that caused this ::command-line signal emission"),
227                           G_VARIANT_TYPE_BYTESTRING_ARRAY, NULL,
228                           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
229                           G_PARAM_STATIC_STRINGS));
230
231   g_object_class_install_property (object_class, PROP_PLATFORM_DATA,
232     g_param_spec_variant ("platform-data",
233                           P_("Platform data"),
234                           P_("Platform-specific data for the commandline"),
235                           G_VARIANT_TYPE ("a{sv}"), NULL,
236                           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
237                           G_PARAM_STATIC_STRINGS));
238
239   g_object_class_install_property (object_class, PROP_IS_REMOTE,
240     g_param_spec_boolean ("is-remote",
241                           P_("Is remote"),
242                           P_("TRUE if this is a remote commandline"),
243                           FALSE,
244                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
245
246   g_type_class_add_private (class, sizeof (GApplicationCommandLinePrivate));
247 }
248
249
250 /**
251  * g_application_command_line_get_arguments:
252  * @cmdline: a #GApplicationCommandLine
253  * @argc: the length of the arguments array, or %NULL
254  *
255  * Gets the list of arguments that was passed on the command line.
256  *
257  * The strings in the array may contain non-utf8 data.
258  *
259  * The return value is %NULL-terminated and should be freed using
260  * g_strfreev().
261  *
262  * Returns: the string array containing the arguments (the argv)
263  *
264  * Since: 2.28
265  **/
266 gchar **
267 g_application_command_line_get_arguments (GApplicationCommandLine *cmdline,
268                                           int                     *argc)
269 {
270   gchar **argv;
271   gsize len;
272
273   g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
274
275   argv = g_variant_dup_bytestring_array (cmdline->priv->arguments, &len);
276
277   if (argc)
278     *argc = len;
279
280   return argv;
281 }
282
283 /**
284  * g_application_command_line_get_cwd:
285  * @cmdline: a #GApplicationCommandLine
286  *
287  * Gets the working directory of the command line invocation.  The
288  * string may contain non-utf8 data.
289  *
290  * It is possible that the remote application did not send a working
291  * directory, so this may be %NULL.
292  *
293  * The return value should not be modified or freed and is valid for as
294  * long as @cmdline exists.
295  *
296  * Returns: the current directory, or %NULL
297  *
298  * Since: 2.28
299  **/
300 const gchar *
301 g_application_command_line_get_cwd (GApplicationCommandLine *cmdline)
302 {
303   if (cmdline->priv->cwd)
304     return g_variant_get_bytestring (cmdline->priv->cwd);
305   else
306     return NULL;
307 }
308
309 /**
310  * g_application_command_line_get_environ:
311  * @cmdline: a #GApplicationCommandLine
312  *
313  * Gets the contents of the 'environ' variable of the command line
314  * invocation, as would be returned by g_get_environ().  The strings may
315  * contain non-utf8 data.
316  *
317  * The remote application usually does not send an environment.  Use
318  * %G_APPLICATION_SEND_ENVIRONMENT to affect that.  Even with this flag
319  * set it is possible that the environment is still not available (due
320  * to invocation messages from other applications).
321  *
322  * The return value should not be modified or freed and is valid for as
323  * long as @cmdline exists.
324  *
325  * Returns: the environment strings, or %NULL if they were not sent
326  * 
327  * Since: 2.28
328  **/
329 const gchar * const *
330 g_application_command_line_get_environ (GApplicationCommandLine *cmdline)
331 {
332   return cmdline->priv->environ;
333 }
334
335 /**
336  * g_application_command_line_getenv:
337  * @cmdline: a #GApplicationCommandLine
338  * @name: the environment variable to get
339  *
340  * Gets the value of a particular environment variable of the command
341  * line invocation, as would be returned by g_getenv().  The strings may
342  * contain non-utf8 data.
343  *
344  * The remote application usually does not send an environment.  Use
345  * %G_APPLICATION_SEND_ENVIRONMENT to affect that.  Even with this flag
346  * set it is possible that the environment is still not available (due
347  * to invocation messages from other applications).
348  *
349  * The return value should not be modified or freed and is valid for as
350  * long as @cmdline exists.
351  *
352  * Returns: the value of the variable, or %NULL if unset or unsent
353  * 
354  * Since: 2.28
355  **/
356 const gchar *
357 g_application_command_line_getenv (GApplicationCommandLine *cmdline,
358                                    const gchar             *name)
359 {
360   gint length = strlen (name);
361   gint i;
362
363   /* TODO: expand on windows */
364   if (cmdline->priv->environ)
365     for (i = 0; cmdline->priv->environ[i]; i++)
366       if (strncmp (cmdline->priv->environ[i], name, length) == 0 &&
367           cmdline->priv->environ[i][length] == '=')
368         return cmdline->priv->environ[i] + length + 1;
369
370   return NULL;
371 }
372
373 /**
374  * g_application_command_line_get_is_remote:
375  * @cmdline: a #GApplicationCommandLine
376  *
377  * Determines if @cmdline represents a remote invocation.
378  *
379  * Returns: %TRUE if the invocation was remote
380  *
381  * Since: 2.28
382  **/
383 gboolean
384 g_application_command_line_get_is_remote (GApplicationCommandLine *cmdline)
385 {
386   return IS_REMOTE (cmdline);
387 }
388
389 /**
390  * g_application_command_line_print:
391  * @cmdline: a #GApplicationCommandLine
392  * @format: a printf-style format string
393  * @...: arguments, as per @format
394  *
395  * Formats a message and prints it using the stdout print handler in the
396  * invoking process.
397  *
398  * If @cmdline is a local invocation then this is exactly equivalent to
399  * g_print().  If @cmdline is remote then this is equivalent to calling
400  * g_print() in the invoking process.
401  *
402  * Since: 2.28
403  **/
404 void
405 g_application_command_line_print (GApplicationCommandLine *cmdline,
406                                   const gchar             *format,
407                                   ...)
408 {
409   gchar *message;
410   va_list ap;
411
412   g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
413   g_return_if_fail (format != NULL);
414
415   va_start (ap, format);
416   message = g_strdup_vprintf (format, ap);
417   va_end (ap);
418
419   G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
420     ->print_literal (cmdline, message);
421   g_free (message);
422 }
423
424 /**
425  * g_application_command_line_printerr:
426  * @cmdline: a #GApplicationCommandLine
427  * @format: a printf-style format string
428  * @...: arguments, as per @format
429  *
430  * Formats a message and prints it using the stderr print handler in the
431  * invoking process.
432  *
433  * If @cmdline is a local invocation then this is exactly equivalent to
434  * g_printerr().  If @cmdline is remote then this is equivalent to
435  * calling g_printerr() in the invoking process.
436  *
437  * Since: 2.28
438  **/
439 void
440 g_application_command_line_printerr (GApplicationCommandLine *cmdline,
441                                      const gchar             *format,
442                                      ...)
443 {
444   gchar *message;
445   va_list ap;
446
447   g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
448   g_return_if_fail (format != NULL);
449
450   va_start (ap, format);
451   message = g_strdup_vprintf (format, ap);
452   va_end (ap);
453
454   G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)
455     ->printerr_literal (cmdline, message);
456   g_free (message);
457 }
458
459 /**
460  * g_application_command_line_set_exit_status:
461  * @cmdline: a #GApplicationCommandLine
462  * @exit_status: the exit status
463  *
464  * Sets the exit status that will be used when the invoking process
465  * exits.
466  *
467  * The return value of the #GApplication::command-line signal is
468  * passed to this function when the handler returns.  This is the usual
469  * way of setting the exit status.
470  *
471  * In the event that you want the remote invocation to continue running
472  * and want to decide on the exit status in the future, you can use this
473  * call.  For the case of a remote invocation, the remote process will
474  * typically exit when the last reference is dropped on @cmdline.  The
475  * exit status of the remote process will be equal to the last value
476  * that was set with this function.
477  *
478  * In the case that the commandline invocation is local, the situation
479  * is slightly more complicated.  If the commandline invocation results
480  * in the mainloop running (ie: because the use-count of the application
481  * increased to a non-zero value) then the application is considered to
482  * have been 'successful' in a certain sense, and the exit status is
483  * always zero.  If the application use count is zero, though, the exit
484  * status of the local #GApplicationCommandLine is used.
485  *
486  * Since: 2.28
487  **/
488 void
489 g_application_command_line_set_exit_status (GApplicationCommandLine *cmdline,
490                                             int                      exit_status)
491 {
492   g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));
493
494   cmdline->priv->exit_status = exit_status;
495 }
496
497 /**
498  * g_application_command_line_get_exit_status:
499  * @cmdline: a #GApplicationCommandLine
500  *
501  * Gets the exit status of @cmdline.  See
502  * g_application_command_line_set_exit_status() for more information.
503  *
504  * Returns: the exit status
505  *
506  * Since: 2.28
507  **/
508 int
509 g_application_command_line_get_exit_status (GApplicationCommandLine *cmdline)
510 {
511   g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), -1);
512
513   return cmdline->priv->exit_status;
514 }
515
516 /**
517  * g_application_command_line_get_platform_data:
518  * @cmdline: #GApplicationCommandLine
519  *
520  * Gets the platform data associated with the invocation of @cmdline.
521  *
522  * This is a #GVariant dictionary containing information about the
523  * context in which the invocation occured.  It typically contains
524  * information like the current working directory and the startup
525  * notification ID.
526  *
527  * For local invocation, it will be %NULL.
528  *
529  * Returns: the platform data, or %NULL
530  *
531  * Since: 2.28
532  **/
533 GVariant *
534 g_application_command_line_get_platform_data (GApplicationCommandLine *cmdline)
535 {
536   g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL);
537
538   if (cmdline->priv->platform_data)
539     return g_variant_ref (cmdline->priv->platform_data);
540   else
541       return NULL;
542 }