glib/libglib/src/gshell.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* gshell.c - Shell-related utilities
       
     2  *
       
     3  *  Copyright 2000 Red Hat, Inc.
       
     4  *  g_execvpe implementation based on GNU libc execvp:
       
     5  *   Copyright 1991, 92, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
       
     6  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     7  *
       
     8  * GLib is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Lesser General Public License as
       
    10  * published by the Free Software Foundation; either version 2 of the
       
    11  * License, or (at your option) any later version.
       
    12  *
       
    13  * GLib is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16  * Lesser General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Lesser General Public
       
    19  * License along with GLib; see the file COPYING.LIB.  If not, write
       
    20  * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    21  * Boston, MA 02111-1307, USA.
       
    22  */
       
    23 
       
    24 #include "config.h"
       
    25 
       
    26 #include <string.h>
       
    27 
       
    28 #include "glib.h"
       
    29 #include "galias.h"
       
    30 
       
    31 #ifdef _
       
    32 #warning "FIXME remove gettext hack"
       
    33 #endif
       
    34 
       
    35 #include "glibintl.h"
       
    36 
       
    37 #ifdef __SYMBIAN32__
       
    38 #include <glib_wsd.h>
       
    39 #endif
       
    40 
       
    41 #if EMULATOR
       
    42 
       
    43 PLS(quark,g_shell_error_quark ,GQuark)
       
    44 #define quark (*FUNCTION_NAME(quark,g_shell_error_quark )())
       
    45 
       
    46 #endif /* EMULATOR */
       
    47 
       
    48 EXPORT_C GQuark
       
    49 g_shell_error_quark (void)
       
    50 {
       
    51   #if !(EMULATOR)
       
    52   static GQuark quark = 0;
       
    53   #endif /* EMULATOR */
       
    54   
       
    55   if (quark == 0)
       
    56     quark = g_quark_from_static_string ("g-shell-error-quark");
       
    57   return quark;
       
    58 }
       
    59 
       
    60 #if EMULATOR
       
    61 #undef quark 
       
    62 #endif /* EMULATOR */
       
    63 
       
    64 /* Single quotes preserve the literal string exactly. escape
       
    65  * sequences are not allowed; not even \' - if you want a '
       
    66  * in the quoted text, you have to do something like 'foo'\''bar'
       
    67  *
       
    68  * Double quotes allow $ ` " \ and newline to be escaped with backslash.
       
    69  * Otherwise double quotes preserve things literally.
       
    70  */
       
    71 
       
    72 static gboolean 
       
    73 unquote_string_inplace (gchar* str, gchar** end, GError** err)
       
    74 {
       
    75   gchar* dest;
       
    76   gchar* s;
       
    77   gchar quote_char;
       
    78   
       
    79   g_return_val_if_fail(end != NULL, FALSE);
       
    80   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
       
    81   g_return_val_if_fail(str != NULL, FALSE);
       
    82   
       
    83   dest = s = str;
       
    84 
       
    85   quote_char = *s;
       
    86   
       
    87   if (!(*s == '"' || *s == '\''))
       
    88     {
       
    89       if (err)
       
    90         *err = g_error_new(G_SHELL_ERROR,
       
    91                            G_SHELL_ERROR_BAD_QUOTING,
       
    92                            _("Quoted text doesn't begin with a quotation mark"));
       
    93       *end = str;
       
    94       return FALSE;
       
    95     }
       
    96 
       
    97   /* Skip the initial quote mark */
       
    98   ++s;
       
    99 
       
   100   if (quote_char == '"')
       
   101     {
       
   102       while (*s)
       
   103         {
       
   104           g_assert(s > dest); /* loop invariant */
       
   105       
       
   106           switch (*s)
       
   107             {
       
   108             case '"':
       
   109               /* End of the string, return now */
       
   110               *dest = '\0';
       
   111               ++s;
       
   112               *end = s;
       
   113               return TRUE;
       
   114               break;
       
   115 
       
   116             case '\\':
       
   117               /* Possible escaped quote or \ */
       
   118               ++s;
       
   119               switch (*s)
       
   120                 {
       
   121                 case '"':
       
   122                 case '\\':
       
   123                 case '`':
       
   124                 case '$':
       
   125                 case '\n':
       
   126                   *dest = *s;
       
   127                   ++s;
       
   128                   ++dest;
       
   129                   break;
       
   130 
       
   131                 default:
       
   132                   /* not an escaped char */
       
   133                   *dest = '\\';
       
   134                   ++dest;
       
   135                   /* ++s already done. */
       
   136                   break;
       
   137                 }
       
   138               break;
       
   139 
       
   140             default:
       
   141               *dest = *s;
       
   142               ++dest;
       
   143               ++s;
       
   144               break;
       
   145             }
       
   146 
       
   147           g_assert(s > dest); /* loop invariant */
       
   148         }
       
   149     }
       
   150   else
       
   151     {
       
   152       while (*s)
       
   153         {
       
   154           g_assert(s > dest); /* loop invariant */
       
   155           
       
   156           if (*s == '\'')
       
   157             {
       
   158               /* End of the string, return now */
       
   159               *dest = '\0';
       
   160               ++s;
       
   161               *end = s;
       
   162               return TRUE;
       
   163             }
       
   164           else
       
   165             {
       
   166               *dest = *s;
       
   167               ++dest;
       
   168               ++s;
       
   169             }
       
   170 
       
   171           g_assert(s > dest); /* loop invariant */
       
   172         }
       
   173     }
       
   174   
       
   175   /* If we reach here this means the close quote was never encountered */
       
   176 
       
   177   *dest = '\0';
       
   178   
       
   179   if (err)
       
   180     *err = g_error_new(G_SHELL_ERROR,
       
   181                        G_SHELL_ERROR_BAD_QUOTING,
       
   182                        _("Unmatched quotation mark in command line or other shell-quoted text"));
       
   183   *end = s;
       
   184   return FALSE;
       
   185 }
       
   186 
       
   187 /**
       
   188  * g_shell_quote:
       
   189  * @unquoted_string: a literal string
       
   190  * 
       
   191  * Quotes a string so that the shell (/bin/sh) will interpret the
       
   192  * quoted string to mean @unquoted_string. If you pass a filename to
       
   193  * the shell, for example, you should first quote it with this
       
   194  * function.  The return value must be freed with g_free(). The
       
   195  * quoting style used is undefined (single or double quotes may be
       
   196  * used).
       
   197  * 
       
   198  * Return value: quoted string
       
   199  **/
       
   200 EXPORT_C gchar*
       
   201 g_shell_quote (const gchar *unquoted_string)
       
   202 {
       
   203   /* We always use single quotes, because the algorithm is cheesier.
       
   204    * We could use double if we felt like it, that might be more
       
   205    * human-readable.
       
   206    */
       
   207 
       
   208   const gchar *p;
       
   209   GString *dest;
       
   210 
       
   211   g_return_val_if_fail (unquoted_string != NULL, NULL);
       
   212   
       
   213   dest = g_string_new ("'");
       
   214 
       
   215   p = unquoted_string;
       
   216 
       
   217   /* could speed this up a lot by appending chunks of text at a
       
   218    * time.
       
   219    */
       
   220   while (*p)
       
   221     {
       
   222       /* Replace literal ' with a close ', a \', and a open ' */
       
   223       if (*p == '\'')
       
   224         g_string_append (dest, "'\\''");
       
   225       else
       
   226         g_string_append_c (dest, *p);
       
   227 
       
   228       ++p;
       
   229     }
       
   230 
       
   231   /* close the quote */
       
   232   g_string_append_c (dest, '\'');
       
   233   
       
   234   return g_string_free (dest, FALSE);
       
   235 }
       
   236 
       
   237 /**
       
   238  * g_shell_unquote:
       
   239  * @quoted_string: shell-quoted string
       
   240  * @error: error return location or NULL
       
   241  * 
       
   242  * Unquotes a string as the shell (/bin/sh) would. Only handles
       
   243  * quotes; if a string contains file globs, arithmetic operators,
       
   244  * variables, backticks, redirections, or other special-to-the-shell
       
   245  * features, the result will be different from the result a real shell
       
   246  * would produce (the variables, backticks, etc. will be passed
       
   247  * through literally instead of being expanded). This function is
       
   248  * guaranteed to succeed if applied to the result of
       
   249  * g_shell_quote(). If it fails, it returns %NULL and sets the
       
   250  * error. The @quoted_string need not actually contain quoted or
       
   251  * escaped text; g_shell_unquote() simply goes through the string and
       
   252  * unquotes/unescapes anything that the shell would. Both single and
       
   253  * double quotes are handled, as are escapes including escaped
       
   254  * newlines. The return value must be freed with g_free(). Possible
       
   255  * errors are in the #G_SHELL_ERROR domain.
       
   256  * 
       
   257  * Shell quoting rules are a bit strange. Single quotes preserve the
       
   258  * literal string exactly. escape sequences are not allowed; not even
       
   259  * \' - if you want a ' in the quoted text, you have to do something
       
   260  * like 'foo'\''bar'.  Double quotes allow $, `, ", \, and newline to
       
   261  * be escaped with backslash. Otherwise double quotes preserve things
       
   262  * literally.
       
   263  *
       
   264  * Return value: an unquoted string
       
   265  **/
       
   266 EXPORT_C gchar*
       
   267 g_shell_unquote (const gchar *quoted_string,
       
   268                  GError     **error)
       
   269 {
       
   270   gchar *unquoted;
       
   271   gchar *end;
       
   272   gchar *start;
       
   273   GString *retval;
       
   274   
       
   275   g_return_val_if_fail (quoted_string != NULL, NULL);
       
   276   
       
   277   unquoted = g_strdup (quoted_string);
       
   278 
       
   279   start = unquoted;
       
   280   end = unquoted;
       
   281   retval = g_string_new (NULL);
       
   282 
       
   283   /* The loop allows cases such as
       
   284    * "foo"blah blah'bar'woo foo"baz"la la la\'\''foo'
       
   285    */
       
   286   while (*start)
       
   287     {
       
   288       /* Append all non-quoted chars, honoring backslash escape
       
   289        */
       
   290       
       
   291       while (*start && !(*start == '"' || *start == '\''))
       
   292         {
       
   293           if (*start == '\\')
       
   294             {
       
   295               /* all characters can get escaped by backslash,
       
   296                * except newline, which is removed if it follows
       
   297                * a backslash outside of quotes
       
   298                */
       
   299               
       
   300               ++start;
       
   301               if (*start)
       
   302                 {
       
   303                   if (*start != '\n')
       
   304                     g_string_append_c (retval, *start);
       
   305                   ++start;
       
   306                 }
       
   307             }
       
   308           else
       
   309             {
       
   310               g_string_append_c (retval, *start);
       
   311               ++start;
       
   312             }
       
   313         }
       
   314 
       
   315       if (*start)
       
   316         {
       
   317           if (!unquote_string_inplace (start, &end, error))
       
   318             {
       
   319               goto error;
       
   320             }
       
   321           else
       
   322             {
       
   323               g_string_append (retval, start);
       
   324               start = end;
       
   325             }
       
   326         }
       
   327     }
       
   328 
       
   329   g_free (unquoted);
       
   330   return g_string_free (retval, FALSE);
       
   331   
       
   332  error:
       
   333   g_assert (error == NULL || *error != NULL);
       
   334   
       
   335   g_free (unquoted);
       
   336   g_string_free (retval, TRUE);
       
   337   return NULL;
       
   338 }
       
   339 
       
   340 /* g_parse_argv() does a semi-arbitrary weird subset of the way
       
   341  * the shell parses a command line. We don't do variable expansion,
       
   342  * don't understand that operators are tokens, don't do tilde expansion,
       
   343  * don't do command substitution, no arithmetic expansion, IFS gets ignored,
       
   344  * don't do filename globs, don't remove redirection stuff, etc.
       
   345  *
       
   346  * READ THE UNIX98 SPEC on "Shell Command Language" before changing
       
   347  * the behavior of this code.
       
   348  *
       
   349  * Steps to parsing the argv string:
       
   350  *
       
   351  *  - tokenize the string (but since we ignore operators,
       
   352  *    our tokenization may diverge from what the shell would do)
       
   353  *    note that tokenization ignores the internals of a quoted
       
   354  *    word and it always splits on spaces, not on IFS even
       
   355  *    if we used IFS. We also ignore "end of input indicator"
       
   356  *    (I guess this is control-D?)
       
   357  *
       
   358  *    Tokenization steps, from UNIX98 with operator stuff removed,
       
   359  *    are:
       
   360  * 
       
   361  *    1) "If the current character is backslash, single-quote or
       
   362  *        double-quote (\, ' or ") and it is not quoted, it will affect
       
   363  *        quoting for subsequent characters up to the end of the quoted
       
   364  *        text. The rules for quoting are as described in Quoting
       
   365  *        . During token recognition no substitutions will be actually
       
   366  *        performed, and the result token will contain exactly the
       
   367  *        characters that appear in the input (except for newline
       
   368  *        character joining), unmodified, including any embedded or
       
   369  *        enclosing quotes or substitution operators, between the quote
       
   370  *        mark and the end of the quoted text. The token will not be
       
   371  *        delimited by the end of the quoted field."
       
   372  *
       
   373  *    2) "If the current character is an unquoted newline character,
       
   374  *        the current token will be delimited."
       
   375  *
       
   376  *    3) "If the current character is an unquoted blank character, any
       
   377  *        token containing the previous character is delimited and the
       
   378  *        current character will be discarded."
       
   379  *
       
   380  *    4) "If the previous character was part of a word, the current
       
   381  *        character will be appended to that word."
       
   382  *
       
   383  *    5) "If the current character is a "#", it and all subsequent
       
   384  *        characters up to, but excluding, the next newline character
       
   385  *        will be discarded as a comment. The newline character that
       
   386  *        ends the line is not considered part of the comment. The
       
   387  *        "#" starts a comment only when it is at the beginning of a
       
   388  *        token. Since the search for the end-of-comment does not
       
   389  *        consider an escaped newline character specially, a comment
       
   390  *        cannot be continued to the next line."
       
   391  *
       
   392  *    6) "The current character will be used as the start of a new word."
       
   393  *
       
   394  *
       
   395  *  - for each token (word), perform portions of word expansion, namely
       
   396  *    field splitting (using default whitespace IFS) and quote
       
   397  *    removal.  Field splitting may increase the number of words.
       
   398  *    Quote removal does not increase the number of words.
       
   399  *
       
   400  *   "If the complete expansion appropriate for a word results in an
       
   401  *   empty field, that empty field will be deleted from the list of
       
   402  *   fields that form the completely expanded command, unless the
       
   403  *   original word contained single-quote or double-quote characters."
       
   404  *    - UNIX98 spec
       
   405  *
       
   406  *
       
   407  */
       
   408 
       
   409 static inline void
       
   410 ensure_token (GString **token)
       
   411 {
       
   412   if (*token == NULL)
       
   413     *token = g_string_new (NULL);
       
   414 }
       
   415 
       
   416 static void
       
   417 delimit_token (GString **token,
       
   418                GSList **retval)
       
   419 {
       
   420   if (*token == NULL)
       
   421     return;
       
   422 
       
   423   *retval = g_slist_prepend (*retval, g_string_free (*token, FALSE));
       
   424 
       
   425   *token = NULL;
       
   426 }
       
   427 
       
   428 static GSList*
       
   429 tokenize_command_line (const gchar *command_line,
       
   430                        GError **error)
       
   431 {
       
   432   gchar current_quote;
       
   433   const gchar *p;
       
   434   GString *current_token = NULL;
       
   435   GSList *retval = NULL;
       
   436   gboolean quoted;;
       
   437 
       
   438   current_quote = '\0';
       
   439   quoted = FALSE;
       
   440   p = command_line;
       
   441  
       
   442   while (*p)
       
   443     {
       
   444       if (current_quote == '\\')
       
   445         {
       
   446           if (*p == '\n')
       
   447             {
       
   448               /* we append nothing; backslash-newline become nothing */
       
   449             }
       
   450           else
       
   451             {
       
   452               /* we append the backslash and the current char,
       
   453                * to be interpreted later after tokenization
       
   454                */
       
   455               ensure_token (&current_token);
       
   456               g_string_append_c (current_token, '\\');
       
   457               g_string_append_c (current_token, *p);
       
   458             }
       
   459 
       
   460           current_quote = '\0';
       
   461         }
       
   462       else if (current_quote == '#')
       
   463         {
       
   464           /* Discard up to and including next newline */
       
   465           while (*p && *p != '\n')
       
   466             ++p;
       
   467 
       
   468           current_quote = '\0';
       
   469           
       
   470           if (*p == '\0')
       
   471             break;
       
   472         }
       
   473       else if (current_quote)
       
   474         {
       
   475           if (*p == current_quote &&
       
   476               /* check that it isn't an escaped double quote */
       
   477               !(current_quote == '"' && quoted))
       
   478             {
       
   479               /* close the quote */
       
   480               current_quote = '\0';
       
   481             }
       
   482 
       
   483           /* Everything inside quotes, and the close quote,
       
   484            * gets appended literally.
       
   485            */
       
   486 
       
   487           ensure_token (&current_token);
       
   488           g_string_append_c (current_token, *p);
       
   489         }
       
   490       else
       
   491         {
       
   492           switch (*p)
       
   493             {
       
   494             case '\n':
       
   495               delimit_token (&current_token, &retval);
       
   496               break;
       
   497 
       
   498             case ' ':
       
   499             case '\t':
       
   500               /* If the current token contains the previous char, delimit
       
   501                * the current token. A nonzero length
       
   502                * token should always contain the previous char.
       
   503                */
       
   504               if (current_token &&
       
   505                   current_token->len > 0)
       
   506                 {
       
   507                   delimit_token (&current_token, &retval);
       
   508                 }
       
   509               
       
   510               /* discard all unquoted blanks (don't add them to a token) */
       
   511               break;
       
   512 
       
   513 
       
   514               /* single/double quotes are appended to the token,
       
   515                * escapes are maybe appended next time through the loop,
       
   516                * comment chars are never appended.
       
   517                */
       
   518               
       
   519             case '\'':
       
   520             case '"':
       
   521               ensure_token (&current_token);
       
   522               g_string_append_c (current_token, *p);
       
   523 
       
   524               /* FALL THRU */
       
   525               
       
   526             case '#':
       
   527             case '\\':
       
   528               current_quote = *p;
       
   529               break;
       
   530 
       
   531             default:
       
   532               /* Combines rules 4) and 6) - if we have a token, append to it,
       
   533                * otherwise create a new token.
       
   534                */
       
   535               ensure_token (&current_token);
       
   536               g_string_append_c (current_token, *p);
       
   537               break;
       
   538             }
       
   539         }
       
   540 
       
   541       /* We need to count consecutive backslashes mod 2, 
       
   542        * to detect escaped doublequotes.
       
   543        */
       
   544       if (*p != '\\')
       
   545 	quoted = FALSE;
       
   546       else
       
   547 	quoted = !quoted;
       
   548 
       
   549       ++p;
       
   550     }
       
   551 
       
   552   delimit_token (&current_token, &retval);
       
   553 
       
   554   if (current_quote)
       
   555     {
       
   556       if (current_quote == '\\')
       
   557         g_set_error (error,
       
   558                      G_SHELL_ERROR,
       
   559                      G_SHELL_ERROR_BAD_QUOTING,
       
   560                      _("Text ended just after a '\\' character."
       
   561                        " (The text was '%s')"),
       
   562                      command_line);
       
   563       else
       
   564         g_set_error (error,
       
   565                      G_SHELL_ERROR,
       
   566                      G_SHELL_ERROR_BAD_QUOTING,
       
   567                      _("Text ended before matching quote was found for %c."
       
   568                        " (The text was '%s')"),
       
   569                      current_quote, command_line);
       
   570       
       
   571       goto error;
       
   572     }
       
   573 
       
   574   if (retval == NULL)
       
   575     {
       
   576       g_set_error (error,
       
   577                    G_SHELL_ERROR,
       
   578                    G_SHELL_ERROR_EMPTY_STRING,
       
   579                    _("Text was empty (or contained only whitespace)"));
       
   580 
       
   581       goto error;
       
   582     }
       
   583   
       
   584   /* we appended backward */
       
   585   retval = g_slist_reverse (retval);
       
   586 
       
   587   return retval;
       
   588 
       
   589  error:
       
   590   g_assert (error == NULL || *error != NULL);
       
   591   
       
   592   if (retval)
       
   593     {
       
   594       g_slist_foreach (retval, (GFunc)g_free, NULL);
       
   595       g_slist_free (retval);
       
   596     }
       
   597 
       
   598   return NULL;
       
   599 }
       
   600 
       
   601 /**
       
   602  * g_shell_parse_argv:
       
   603  * @command_line: command line to parse
       
   604  * @argcp: return location for number of args
       
   605  * @argvp: return location for array of args
       
   606  * @error: return location for error
       
   607  * 
       
   608  * Parses a command line into an argument vector, in much the same way
       
   609  * the shell would, but without many of the expansions the shell would
       
   610  * perform (variable expansion, globs, operators, filename expansion,
       
   611  * etc. are not supported). The results are defined to be the same as
       
   612  * those you would get from a UNIX98 /bin/sh, as long as the input
       
   613  * contains none of the unsupported shell expansions. If the input
       
   614  * does contain such expansions, they are passed through
       
   615  * literally. Possible errors are those from the #G_SHELL_ERROR
       
   616  * domain. Free the returned vector with g_strfreev().
       
   617  * 
       
   618  * Return value: %TRUE on success, %FALSE if error set
       
   619  **/
       
   620 EXPORT_C gboolean
       
   621 g_shell_parse_argv (const gchar *command_line,
       
   622                     gint        *argcp,
       
   623                     gchar     ***argvp,
       
   624                     GError     **error)
       
   625 {
       
   626   /* Code based on poptParseArgvString() from libpopt */
       
   627   gint argc = 0;
       
   628   gchar **argv = NULL;
       
   629   GSList *tokens = NULL;
       
   630   gint i;
       
   631   GSList *tmp_list;
       
   632   
       
   633   g_return_val_if_fail (command_line != NULL, FALSE);
       
   634 
       
   635   tokens = tokenize_command_line (command_line, error);
       
   636   if (tokens == NULL)
       
   637     return FALSE;
       
   638 
       
   639   /* Because we can't have introduced any new blank space into the
       
   640    * tokens (we didn't do any new expansions), we don't need to
       
   641    * perform field splitting. If we were going to honor IFS or do any
       
   642    * expansions, we would have to do field splitting on each word
       
   643    * here. Also, if we were going to do any expansion we would need to
       
   644    * remove any zero-length words that didn't contain quotes
       
   645    * originally; but since there's no expansion we know all words have
       
   646    * nonzero length, unless they contain quotes.
       
   647    * 
       
   648    * So, we simply remove quotes, and don't do any field splitting or
       
   649    * empty word removal, since we know there was no way to introduce
       
   650    * such things.
       
   651    */
       
   652 
       
   653   argc = g_slist_length (tokens);
       
   654   argv = g_new0 (gchar*, argc + 1);
       
   655   i = 0;
       
   656   tmp_list = tokens;
       
   657   while (tmp_list)
       
   658     {
       
   659       argv[i] = g_shell_unquote (tmp_list->data, error);
       
   660 
       
   661       /* Since we already checked that quotes matched up in the
       
   662        * tokenizer, this shouldn't be possible to reach I guess.
       
   663        */
       
   664       if (argv[i] == NULL)
       
   665         goto failed;
       
   666 
       
   667       tmp_list = g_slist_next (tmp_list);
       
   668       ++i;
       
   669     }
       
   670   
       
   671   g_slist_foreach (tokens, (GFunc)g_free, NULL);
       
   672   g_slist_free (tokens);
       
   673   
       
   674   if (argcp)
       
   675     *argcp = argc;
       
   676 
       
   677   if (argvp)
       
   678     *argvp = argv;
       
   679   else
       
   680     g_strfreev (argv);
       
   681 
       
   682   return TRUE;
       
   683 
       
   684  failed:
       
   685 
       
   686   g_assert (error == NULL || *error != NULL);
       
   687   g_strfreev (argv);
       
   688   g_slist_foreach (tokens, (GFunc) g_free, NULL);
       
   689   g_slist_free (tokens);
       
   690   
       
   691   return FALSE;
       
   692 }
       
   693 
       
   694 #define __G_SHELL_C__
       
   695 #include "galiasdef.c"