Coverage report for dbus/dbus-shell.c.gcov

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