(root)/
m4-1.4.19/
tests/
test-spawn-pipe-script.c
       1  /* Test of create_pipe_in/wait_subprocess.
       2     Copyright (C) 2020-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, or (at your option)
       7     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  #include <config.h>
      18  
      19  #include "spawn-pipe.h"
      20  #include "wait-process.h"
      21  
      22  #include <errno.h>
      23  #include <stdbool.h>
      24  #include <stdio.h>
      25  #include <string.h>
      26  #include <unistd.h>
      27  
      28  #include "macros.h"
      29  
      30  int
      31  main ()
      32  {
      33    /* Check an invocation of an executable script.
      34       This should only be supported if the script has a '#!' marker; otherwise
      35       it is unsecure: <https://sourceware.org/bugzilla/show_bug.cgi?id=13134>.
      36       POSIX says that the execlp() and execvp() functions support executing
      37       shell scripts
      38       <https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html>,
      39       but this is considered an antiquated feature.  */
      40    int fd[1];
      41    pid_t pid;
      42  
      43    {
      44      size_t i;
      45  
      46      for (i = 0; i < 2; i++)
      47        {
      48          const char *progname =
      49            (i == 0 ? "executable-script" : "executable-script.sh");
      50          const char *prog_path =
      51            (i == 0 ? SRCDIR "executable-script" : SRCDIR "executable-script.sh");
      52          const char *prog_argv[2] = { prog_path, NULL };
      53  
      54          pid = create_pipe_in (progname, prog_argv[0], prog_argv, NULL,
      55                                NULL, false, true, false, fd);
      56          if (pid >= 0)
      57            {
      58              /* Wait for child.  */
      59              ASSERT (wait_subprocess (pid, progname, true, true, true, false,
      60                                       NULL)
      61                      == 127);
      62            }
      63          else
      64            {
      65              ASSERT (pid == -1);
      66              ASSERT (errno == ENOEXEC);
      67            }
      68        }
      69    }
      70  
      71  #if defined _WIN32 && !defined __CYGWIN__
      72    /* On native Windows, scripts - even with '#!' marker - are not executable.
      73       Only .bat and .cmd files are.  */
      74    fprintf (stderr, "Skipping test: scripts are not executable on this platform.\n");
      75    return 77;
      76  #else
      77    {
      78      const char *progname = "executable-shell-script";
      79      const char *prog_path = SRCDIR "executable-shell-script";
      80      const char *prog_argv[2] = { prog_path, NULL };
      81  
      82      pid = create_pipe_in (progname, prog_argv[0], prog_argv, NULL,
      83                            NULL, false, true, false, fd);
      84      ASSERT (pid >= 0);
      85      ASSERT (fd[0] > STDERR_FILENO);
      86  
      87      /* Get child's output.  */
      88      char buffer[1024];
      89      FILE *fp = fdopen (fd[0], "r");
      90      ASSERT (fp != NULL);
      91      ASSERT (fread (buffer, 1, sizeof (buffer), fp) == 11);
      92  
      93      /* Check the result.  */
      94      ASSERT (memcmp (buffer, "Halle Potta", 11) == 0);
      95  
      96      /* Wait for child.  */
      97      ASSERT (wait_subprocess (pid, progname, true, false, true, true, NULL) == 0);
      98  
      99      ASSERT (fclose (fp) == 0);
     100    }
     101  
     102    return 0;
     103  #endif
     104  }