static dbus_bool_t test_command_line (const char *arg1, ...) { int i, original_argc, shell_argc; char **shell_argv; char **original_argv; char *command_line, *tmp; DBusString str; DBusList *list = NULL, *node; va_list var_args; DBusError error; va_start (var_args, arg1); _dbus_list_append (&list, (char *)arg1); do { tmp = va_arg (var_args, char *); if (!tmp) break; _dbus_list_append (&list, tmp); } while (tmp); va_end (var_args); original_argc = _dbus_list_get_length (&list); original_argv = dbus_new (char *, original_argc); _dbus_string_init (&str); for (i = 0, node = _dbus_list_get_first_link (&list); i < original_argc && node; i++, node = _dbus_list_get_next_link (&list, node)) { original_argv[i] = node->data; if (i > 0) _dbus_string_append_byte (&str, ' '); _dbus_string_append (&str, original_argv[i]); } _dbus_list_clear (&list); command_line = _dbus_string_get_data (&str); printf ("\n\nTesting command line '%s'\n", command_line); dbus_error_init (&error); if (!_dbus_shell_parse_argv (command_line, &shell_argc, &shell_argv, &error)) { fprintf (stderr, "Error parsing command line: %s\n", error.message ? error.message : ""); return FALSE; } else { if (shell_argc != original_argc) { printf ("Number of arguments returned (%d) don't match original (%d)\n", shell_argc, original_argc); return FALSE; } printf ("Number of arguments: %d\n", shell_argc); for (i = 0; i < shell_argc; i++) { char *unquoted; unquoted = _dbus_shell_unquote (original_argv[i]); if (strcmp (unquoted ? unquoted : "", shell_argv[i] ? shell_argv[i] : "")) { printf ("Position %d, returned argument (%s) does not match original (%s)\n", i, shell_argv[i], unquoted); dbus_free (unquoted); return FALSE; } dbus_free (unquoted); if (shell_argv[i]) printf ("Argument %d = %s\n", i, shell_argv[i]); } dbus_free_string_array (shell_argv); } _dbus_string_free (&str); return TRUE; }
/** * _dbus_shell_parse_argv: * * Parses a command line into an argument vector, in much the same way * the shell would, but without many of the expansions the shell would * perform (variable expansion, globs, operators, filename expansion, * etc. are not supported). The results are defined to be the same as * those you would get from a UNIX98 /bin/sh, as long as the input * contains none of the unsupported shell expansions. If the input * does contain such expansions, they are passed through * literally. Free the returned vector with dbus_free_string_array(). * * @command_line: command line to parse * @argcp: return location for number of args * @argvp: return location for array of args * @error: error information **/ dbus_bool_t _dbus_shell_parse_argv (const char *command_line, int *argcp, char ***argvp, DBusError *error) { /* Code based on poptParseArgvString() from libpopt */ int argc = 0; char **argv = NULL; DBusList *tokens = NULL; int i; DBusList *tmp_list; if (!command_line) { _dbus_verbose ("Command line is NULL\n"); return FALSE; } tokens = tokenize_command_line (command_line, error); if (tokens == NULL) { _dbus_verbose ("No tokens for command line '%s'\n", command_line); return FALSE; } /* Because we can't have introduced any new blank space into the * tokens (we didn't do any new expansions), we don't need to * perform field splitting. If we were going to honor IFS or do any * expansions, we would have to do field splitting on each word * here. Also, if we were going to do any expansion we would need to * remove any zero-length words that didn't contain quotes * originally; but since there's no expansion we know all words have * nonzero length, unless they contain quotes. * * So, we simply remove quotes, and don't do any field splitting or * empty word removal, since we know there was no way to introduce * such things. */ argc = _dbus_list_get_length (&tokens); argv = dbus_new (char *, argc + 1); if (!argv) { _DBUS_SET_OOM (error); goto error; } i = 0; tmp_list = tokens; while (tmp_list) { argv[i] = _dbus_shell_unquote (tmp_list->data); if (!argv[i]) { int j; for (j = 0; j < i; j++) dbus_free(argv[j]); dbus_free (argv); _DBUS_SET_OOM (error); goto error; } tmp_list = _dbus_list_get_next_link (&tokens, tmp_list); ++i; } argv[argc] = NULL; _dbus_list_foreach (&tokens, (DBusForeachFunction) dbus_free, NULL); _dbus_list_clear (&tokens); if (argcp) *argcp = argc; if (argvp) *argvp = argv; else dbus_free_string_array (argv); return TRUE; error: _dbus_list_foreach (&tokens, (DBusForeachFunction) dbus_free, NULL); _dbus_list_clear (&tokens); return FALSE; }