* Boston, MA 02111-1307, USA.
*/
-#include "glib.h"
+#include "config.h"
+
#include <string.h>
+#include "glib.h"
+
#ifdef _
#warning "FIXME remove gettext hack"
#endif
-#define _(x) x
+#include "glibintl.h"
+#include "galias.h"
+
+/**
+ * SECTION: shell
+ * @title: Shell-related Utilities
+ * @short_description: shell-like commandline handling
+ **/
+
+/**
+ * G_SHELL_ERROR:
+ *
+ * Error domain for shell functions. Errors in this domain will be from
+ * the #GShellError enumeration. See #GError for information on error
+ * domains.
+ **/
+/**
+ * GShellError:
+ * @G_SHELL_ERROR_BAD_QUOTING: Mismatched or otherwise mangled quoting.
+ * @G_SHELL_ERROR_EMPTY_STRING: String to be parsed was empty.
+ * @G_SHELL_ERROR_FAILED: Some other error.
+ *
+ * Error codes returned by shell functions.
+ **/
GQuark
g_shell_error_quark (void)
{
- static GQuark quark = 0;
- if (quark == 0)
- quark = g_quark_from_static_string ("g-shell-error-quark");
- return quark;
+ return g_quark_from_static_string ("g-shell-error-quark");
}
/* Single quotes preserve the literal string exactly. escape
* Otherwise double quotes preserve things literally.
*/
-gboolean
+static gboolean
unquote_string_inplace (gchar* str, gchar** end, GError** err)
{
gchar* dest;
if (!(*s == '"' || *s == '\''))
{
- if (err)
- *err = g_error_new(G_SHELL_ERROR,
+ g_set_error_literal (err,
+ G_SHELL_ERROR,
G_SHELL_ERROR_BAD_QUOTING,
_("Quoted text doesn't begin with a quotation mark"));
*end = str;
*dest = '\0';
- if (err)
- *err = g_error_new(G_SHELL_ERROR,
+ g_set_error_literal (err,
+ G_SHELL_ERROR,
G_SHELL_ERROR_BAD_QUOTING,
_("Unmatched quotation mark in command line or other shell-quoted text"));
*end = s;
{
/* Replace literal ' with a close ', a \', and a open ' */
if (*p == '\'')
- g_string_append (dest, "'\''");
+ g_string_append (dest, "'\\''");
else
g_string_append_c (dest, *p);
* would produce (the variables, backticks, etc. will be passed
* through literally instead of being expanded). This function is
* guaranteed to succeed if applied to the result of
- * g_shell_quote(). If it fails, it returns NULL and sets the
+ * g_shell_quote(). If it fails, it returns %NULL and sets the
* error. The @quoted_string need not actually contain quoted or
* escaped text; g_shell_unquote() simply goes through the string and
* unquotes/unescapes anything that the shell would. Both single and
* newlines. The return value must be freed with g_free(). Possible
* errors are in the #G_SHELL_ERROR domain.
*
+ * Shell quoting rules are a bit strange. Single quotes preserve the
+ * literal string exactly. escape sequences are not allowed; not even
+ * \' - if you want a ' in the quoted text, you have to do something
+ * like 'foo'\''bar'. Double quotes allow $, `, ", \, and newline to
+ * be escaped with backslash. Otherwise double quotes preserve things
+ * literally.
+ *
* Return value: an unquoted string
**/
gchar*
start = unquoted;
end = unquoted;
- retval = g_string_new ("");
+ retval = g_string_new (NULL);
/* The loop allows cases such as
* "foo"blah blah'bar'woo foo"baz"la la la\'\''foo'
}
}
+ g_free (unquoted);
return g_string_free (retval, FALSE);
error:
ensure_token (GString **token)
{
if (*token == NULL)
- *token = g_string_new ("");
+ *token = g_string_new (NULL);
}
static void
const gchar *p;
GString *current_token = NULL;
GSList *retval = NULL;
-
+ gboolean quoted;;
+
current_quote = '\0';
+ quoted = FALSE;
p = command_line;
-
+
while (*p)
{
if (current_quote == '\\')
{
if (*p == current_quote &&
/* check that it isn't an escaped double quote */
- !(current_quote == '"' && p != command_line && *(p - 1) == '\\'))
+ !(current_quote == '"' && quoted))
{
/* close the quote */
current_quote = '\0';
}
}
+ /* We need to count consecutive backslashes mod 2,
+ * to detect escaped doublequotes.
+ */
+ if (*p != '\\')
+ quoted = FALSE;
+ else
+ quoted = !quoted;
+
++p;
}
g_set_error (error,
G_SHELL_ERROR,
G_SHELL_ERROR_BAD_QUOTING,
- _("Text ended just after a '\' character."
+ _("Text ended just after a '\\' character."
" (The text was '%s')"),
command_line);
else
if (retval == NULL)
{
- g_set_error (error,
- G_SHELL_ERROR,
- G_SHELL_ERROR_EMPTY_STRING,
- _("Text was empty (or contained only whitespace)"));
+ g_set_error_literal (error,
+ G_SHELL_ERROR,
+ G_SHELL_ERROR_EMPTY_STRING,
+ _("Text was empty (or contained only whitespace)"));
goto error;
}
* contains none of the unsupported shell expansions. If the input
* does contain such expansions, they are passed through
* literally. Possible errors are those from the #G_SHELL_ERROR
- * domain.
+ * domain. Free the returned vector with g_strfreev().
*
- * Return value: TRUE on success, FALSE if error set
+ * Return value: %TRUE on success, %FALSE if error set
**/
gboolean
g_shell_parse_argv (const gchar *command_line,
return FALSE;
}
+
+#define __G_SHELL_C__
+#include "galiasdef.c"