root/maint/gnulib/tests/test-sh-quote.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_one
  2. main

   1 /* Test of sh-quote module.
   2    Copyright (C) 2012-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Bruno Haible <bruno@clisp.org>, 2012.  */
  18 
  19 #include <config.h>
  20 
  21 /* Specification.  */
  22 #include "sh-quote.h"
  23 
  24 #include <limits.h>
  25 #include <string.h>
  26 
  27 #include "macros.h"
  28 
  29 static void
  30 check_one (const char *input, const char *expected)
     /* [previous][next][first][last][top][bottom][index][help] */
  31 {
  32   char buf[1000];
  33   size_t output_len;
  34   char *output;
  35   char *bufend;
  36 
  37   output_len = shell_quote_length (input);
  38 
  39   output = shell_quote (input);
  40   ASSERT (strlen (output) == output_len);
  41 
  42   ASSERT (output_len <= sizeof (buf) - 2);
  43   memset (buf, '\0', output_len + 1);
  44   buf[output_len + 1] = '%';
  45   bufend = shell_quote_copy (buf, input);
  46   ASSERT (bufend == buf + output_len);
  47   ASSERT (memcmp (buf, output, output_len + 1) == 0);
  48   ASSERT (buf[output_len + 1] == '%');
  49 
  50   ASSERT (strcmp (output, expected) == 0);
  51 
  52   free (output);
  53 }
  54 
  55 int
  56 main (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58   /* Check the shell_quote_length, shell_quote_copy, shell_quote functions.  */
  59   {
  60     int c;
  61 
  62     /* Empty argument.  */
  63     check_one ("", "''");
  64 
  65     /* Identifier or number.  */
  66     check_one ("foo", "foo");
  67     check_one ("phr0ck", "phr0ck");
  68 
  69     /* Whitespace would be interpreted as argument separator by the shell.  */
  70     check_one ("foo\tbar", "'foo\tbar'");
  71     check_one ("foo\nbar", "'foo\nbar'");
  72     check_one ("foo\rbar", "'foo\rbar'");
  73     check_one ("foo bar", "'foo bar'");
  74 
  75     /* '!' at the beginning of argv[0] would introduce a negated command.  */
  76     check_one ("!foo", "'!foo'");
  77 
  78     /* '"' would be interpreted as the start of a string.  */
  79     check_one ("\"foo\"bar", "'\"foo\"bar'");
  80 
  81     /* '#' at the beginning of an argument would be interpreted as the start
  82        of a comment.  */
  83     check_one ("#foo", "'#foo'");
  84 
  85     /* '$' at the beginning of an argument would be interpreted as a variable
  86        reference.  */
  87     check_one ("$foo", "'$foo'");
  88 
  89     /* '&' at the beginning of an argument would be interpreted as a background
  90        task indicator.  */
  91     check_one ("&", "'&'");
  92 
  93     /* "'" would be interpreted as the start of a string.  */
  94     check_one ("'foo'bar", "\"'foo'bar\"");
  95 
  96     /* '(' at the beginning of argv[0] would introduce a subshell command.  */
  97     check_one ("(", "'('");
  98 
  99     /* ')' at the beginning of an argument would be interpreted as the end of
 100        the command.  */
 101     check_one (")", "')'");
 102 
 103     /* '*' would be interpreted as a wildcard character.  */
 104     check_one ("*", "'*'");
 105     check_one ("*foo", "'*foo'");
 106 
 107     /* ';' at the beginning of an argument would be interpreted as an empty
 108        statement in argv[0] and as the end of the command otherwise.  */
 109     check_one (";", "';'");
 110     check_one ("foo;", "'foo;'");
 111 
 112     /* '<' would be interpreted as a redirection of stdin.  */
 113     check_one ("<", "'<'");
 114 
 115     /* '=' inside argv[0] would be interpreted as an environment variable
 116        assignment.  */
 117     check_one ("foo=bar", "'foo=bar'");
 118 
 119     /* '>' would be interpreted as a redirection of stdout.  */
 120     check_one (">", "'>'");
 121 
 122     /* '?' would be interpreted as a wildcard character.  */
 123     check_one ("?", "'?'");
 124     check_one ("foo?bar", "'foo?bar'");
 125 
 126     /* '^' would be interpreted in old /bin/sh, e.g. SunOS 4.1.4.  */
 127     check_one ("^", "'^'");
 128 
 129     /* "[...]" would be interpreted as a wildcard pattern.  */
 130     check_one ("[", "'['");
 131     check_one ("]", "]"); /* or "']'" */
 132 
 133     /* '\' would be interpreted as an escape character.  */
 134     check_one ("\\foo", "'\\foo'");
 135 
 136     /* '`' would be interpreted as the start of a command substitution.  */
 137     check_one ("`foo", "'`foo'");
 138 
 139     /* '{' at the beginning of argv[0] would introduce a complex command.  */
 140     check_one ("{", "'{'");
 141 
 142     /* '|' at the beginning of an argument would be interpreted as a pipe
 143        between commands.  */
 144     check_one ("|", "'|'");
 145 
 146     /* '}' at the beginning of an argument would be interpreted as the end of
 147        the command.  */
 148     check_one ("}", "'}'");
 149 
 150     /* '~' at the beginning of an argument would be interpreted as a reference
 151        to a user's home directory.  */
 152     check_one ("~", "'~'");
 153     check_one ("~foo", "'~foo'");
 154 
 155     /* A string that contains both ' and ".  */
 156     check_one ("foo'bar\"baz", "'foo'\\''bar\"baz'"); /* or "\"foo'bar\\\"baz\"" */
 157 
 158     /* All other characters don't need quoting.  */
 159     for (c = 1; c <= UCHAR_MAX; c++)
 160       if (strchr ("\t\n\r !\"#$&'()*;<=>?^[\\]`{|}~", c) == NULL)
 161         {
 162           char s[5];
 163           s[0] = 'a';
 164           s[1] = (char) c;
 165           s[2] = 'z';
 166           s[3] = (char) c;
 167           s[4] = '\0';
 168 
 169           check_one (s, s);
 170         }
 171   }
 172 
 173   /* Check the shell_quote_argv function.  */
 174   {
 175     const char *argv[1];
 176     char *result;
 177     argv[0] = NULL;
 178     result = shell_quote_argv (argv);
 179     ASSERT (strcmp (result, "") == 0);
 180     free (result);
 181   }
 182   {
 183     const char *argv[2];
 184     char *result;
 185     argv[0] = "foo bar/baz";
 186     argv[1] = NULL;
 187     result = shell_quote_argv (argv);
 188     ASSERT (strcmp (result, "'foo bar/baz'") == 0); /* or "\"foo bar/baz\"" */
 189     free (result);
 190   }
 191   {
 192     const char *argv[3];
 193     char *result;
 194     argv[0] = "foo bar/baz";
 195     argv[1] = "$";
 196     argv[2] = NULL;
 197     result = shell_quote_argv (argv);
 198     ASSERT (strcmp (result, "'foo bar/baz' '$'") == 0); /* or "\"foo bar/baz\" \"\\$\"" */
 199     free (result);
 200   }
 201 
 202   return 0;
 203 }

/* [previous][next][first][last][top][bottom][index][help] */