Blame gnulib-tests/test-sh-quote.c

Packit 33f14e
/* Test of sh-quote module.
Packit 33f14e
   Copyright (C) 2012-2017 Free Software Foundation, Inc.
Packit 33f14e
Packit 33f14e
   This program is free software: you can redistribute it and/or modify
Packit 33f14e
   it under the terms of the GNU General Public License as published by
Packit 33f14e
   the Free Software Foundation; either version 3 of the License, or
Packit 33f14e
   (at your option) any later version.
Packit 33f14e
Packit 33f14e
   This program is distributed in the hope that it will be useful,
Packit 33f14e
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 33f14e
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 33f14e
   GNU General Public License for more details.
Packit 33f14e
Packit 33f14e
   You should have received a copy of the GNU General Public License
Packit 33f14e
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 33f14e
Packit 33f14e
/* Written by Bruno Haible <bruno@clisp.org>, 2012.  */
Packit 33f14e
Packit 33f14e
#include <config.h>
Packit 33f14e
Packit 33f14e
/* Specification.  */
Packit 33f14e
#include "sh-quote.h"
Packit 33f14e
Packit 33f14e
#include <limits.h>
Packit 33f14e
#include <string.h>
Packit 33f14e
Packit 33f14e
#include "macros.h"
Packit 33f14e
Packit 33f14e
static void
Packit 33f14e
check_one (const char *input, const char *expected)
Packit 33f14e
{
Packit 33f14e
  char buf[1000];
Packit 33f14e
  size_t output_len;
Packit 33f14e
  char *output;
Packit 33f14e
  char *bufend;
Packit 33f14e
Packit 33f14e
  output_len = shell_quote_length (input);
Packit 33f14e
Packit 33f14e
  output = shell_quote (input);
Packit 33f14e
  ASSERT (strlen (output) == output_len);
Packit 33f14e
Packit 33f14e
  ASSERT (output_len <= sizeof (buf) - 2);
Packit 33f14e
  memset (buf, '\0', output_len + 1);
Packit 33f14e
  buf[output_len + 1] = '%';
Packit 33f14e
  bufend = shell_quote_copy (buf, input);
Packit 33f14e
  ASSERT (bufend == buf + output_len);
Packit 33f14e
  ASSERT (memcmp (buf, output, output_len + 1) == 0);
Packit 33f14e
  ASSERT (buf[output_len + 1] == '%');
Packit 33f14e
Packit 33f14e
  ASSERT (strcmp (output, expected) == 0);
Packit 33f14e
Packit 33f14e
  free (output);
Packit 33f14e
}
Packit 33f14e
Packit 33f14e
int
Packit 33f14e
main (void)
Packit 33f14e
{
Packit 33f14e
  /* Check the shell_quote_length, shell_quote_copy, shell_quote functions.  */
Packit 33f14e
  {
Packit 33f14e
    int c;
Packit 33f14e
Packit 33f14e
    /* Empty argument.  */
Packit 33f14e
    check_one ("", "''");
Packit 33f14e
Packit 33f14e
    /* Identifier or number.  */
Packit 33f14e
    check_one ("foo", "foo");
Packit 33f14e
    check_one ("phr0ck", "phr0ck");
Packit 33f14e
Packit 33f14e
    /* Whitespace would be interpreted as argument separator by the shell.  */
Packit 33f14e
    check_one ("foo\tbar", "'foo\tbar'");
Packit 33f14e
    check_one ("foo\nbar", "'foo\nbar'");
Packit 33f14e
    check_one ("foo\rbar", "'foo\rbar'");
Packit 33f14e
    check_one ("foo bar", "'foo bar'");
Packit 33f14e
Packit 33f14e
    /* '!' at the beginning of argv[0] would introduce a negated command.  */
Packit 33f14e
    check_one ("!foo", "'!foo'");
Packit 33f14e
Packit 33f14e
    /* '"' would be interpreted as the start of a string.  */
Packit 33f14e
    check_one ("\"foo\"bar", "'\"foo\"bar'");
Packit 33f14e
Packit 33f14e
    /* '#' at the beginning of an argument would be interpreted as the start
Packit 33f14e
       of a comment.  */
Packit 33f14e
    check_one ("#foo", "'#foo'");
Packit 33f14e
Packit 33f14e
    /* '$' at the beginning of an argument would be interpreted as a variable
Packit 33f14e
       reference.  */
Packit 33f14e
    check_one ("$foo", "'$foo'");
Packit 33f14e
Packit 33f14e
    /* '&' at the beginning of an argument would be interpreted as a background
Packit 33f14e
       task indicator.  */
Packit 33f14e
    check_one ("&", "'&'");
Packit 33f14e
Packit 33f14e
    /* "'" would be interpreted as the start of a string.  */
Packit 33f14e
    check_one ("'foo'bar", "\"'foo'bar\"");
Packit 33f14e
Packit 33f14e
    /* '(' at the beginning of argv[0] would introduce a subshell command.  */
Packit 33f14e
    check_one ("(", "'('");
Packit 33f14e
Packit 33f14e
    /* ')' at the beginning of an argument would be interpreted as the end of
Packit 33f14e
       the command.  */
Packit 33f14e
    check_one (")", "')'");
Packit 33f14e
Packit 33f14e
    /* '*' would be interpreted as a wildcard character.  */
Packit 33f14e
    check_one ("*", "'*'");
Packit 33f14e
    check_one ("*foo", "'*foo'");
Packit 33f14e
Packit 33f14e
    /* ';' at the beginning of an argument would be interpreted as an empty
Packit 33f14e
       statement in argv[0] and as the end of the command otherwise.  */
Packit 33f14e
    check_one (";", "';'");
Packit 33f14e
    check_one ("foo;", "'foo;'");
Packit 33f14e
Packit 33f14e
    /* '<' would be interpreted as a redirection of stdin.  */
Packit 33f14e
    check_one ("<", "'<'");
Packit 33f14e
Packit 33f14e
    /* '=' inside argv[0] would be interpreted as an environment variable
Packit 33f14e
       assignment.  */
Packit 33f14e
    check_one ("foo=bar", "'foo=bar'");
Packit 33f14e
Packit 33f14e
    /* '>' would be interpreted as a redirection of stdout.  */
Packit 33f14e
    check_one (">", "'>'");
Packit 33f14e
Packit 33f14e
    /* '?' would be interpreted as a wildcard character.  */
Packit 33f14e
    check_one ("?", "'?'");
Packit 33f14e
    check_one ("foo?bar", "'foo?bar'");
Packit 33f14e
Packit 33f14e
    /* '^' would be interpreted in old /bin/sh, e.g. SunOS 4.1.4.  */
Packit 33f14e
    check_one ("^", "'^'");
Packit 33f14e
Packit 33f14e
    /* "[...]" would be interpreted as a wildcard pattern.  */
Packit 33f14e
    check_one ("[", "'['");
Packit 33f14e
    check_one ("]", "]"); /* or "']'" */
Packit 33f14e
Packit 33f14e
    /* '\' would be interpreted as an escape character.  */
Packit 33f14e
    check_one ("\\foo", "'\\foo'");
Packit 33f14e
Packit 33f14e
    /* '`' would be interpreted as the start of a command substitution.  */
Packit 33f14e
    check_one ("`foo", "'`foo'");
Packit 33f14e
Packit 33f14e
    /* '{' at the beginning of argv[0] would introduce a complex command.  */
Packit 33f14e
    check_one ("{", "'{'");
Packit 33f14e
Packit 33f14e
    /* '|' at the beginning of an argument would be interpreted as a pipe
Packit 33f14e
       between commands.  */
Packit 33f14e
    check_one ("|", "'|'");
Packit 33f14e
Packit 33f14e
    /* '}' at the beginning of an argument would be interpreted as the end of
Packit 33f14e
       the command.  */
Packit 33f14e
    check_one ("}", "'}'");
Packit 33f14e
Packit 33f14e
    /* '~' at the beginning of an argument would be interpreted as a reference
Packit 33f14e
       to a user's home directory.  */
Packit 33f14e
    check_one ("~", "'~'");
Packit 33f14e
    check_one ("~foo", "'~foo'");
Packit 33f14e
Packit 33f14e
    /* A string that contains both ' and ".  */
Packit 33f14e
    check_one ("foo'bar\"baz", "'foo'\\''bar\"baz'"); /* or "\"foo'bar\\\"baz\"" */
Packit 33f14e
Packit 33f14e
    /* All other characters don't need quoting.  */
Packit 33f14e
    for (c = 1; c <= UCHAR_MAX; c++)
Packit 33f14e
      if (strchr ("\t\n\r !\"#$&'()*;<=>?^[\\]`{|}~", c) == NULL)
Packit 33f14e
        {
Packit 33f14e
          char s[5];
Packit 33f14e
          s[0] = 'a';
Packit 33f14e
          s[1] = (char) c;
Packit 33f14e
          s[2] = 'z';
Packit 33f14e
          s[3] = (char) c;
Packit 33f14e
          s[4] = '\0';
Packit 33f14e
Packit 33f14e
          check_one (s, s);
Packit 33f14e
        }
Packit 33f14e
  }
Packit 33f14e
Packit 33f14e
  /* Check the shell_quote_argv function.  */
Packit 33f14e
  {
Packit 33f14e
    char *argv[1];
Packit 33f14e
    char *result;
Packit 33f14e
    argv[0] = NULL;
Packit 33f14e
    result = shell_quote_argv (argv);
Packit 33f14e
    ASSERT (strcmp (result, "") == 0);
Packit 33f14e
    free (result);
Packit 33f14e
  }
Packit 33f14e
  {
Packit 33f14e
    char *argv[2];
Packit 33f14e
    char *result;
Packit 33f14e
    argv[0] = (char *) "foo bar/baz";
Packit 33f14e
    argv[1] = NULL;
Packit 33f14e
    result = shell_quote_argv (argv);
Packit 33f14e
    ASSERT (strcmp (result, "'foo bar/baz'") == 0); /* or "\"foo bar/baz\"" */
Packit 33f14e
    free (result);
Packit 33f14e
  }
Packit 33f14e
  {
Packit 33f14e
    char *argv[3];
Packit 33f14e
    char *result;
Packit 33f14e
    argv[0] = (char *) "foo bar/baz";
Packit 33f14e
    argv[1] = (char *) "$";
Packit 33f14e
    argv[2] = NULL;
Packit 33f14e
    result = shell_quote_argv (argv);
Packit 33f14e
    ASSERT (strcmp (result, "'foo bar/baz' '$'") == 0); /* or "\"foo bar/baz\" \"\\$\"" */
Packit 33f14e
    free (result);
Packit 33f14e
  }
Packit 33f14e
Packit 33f14e
  return 0;
Packit 33f14e
}