root/maint/gnulib/tests/test-posix_spawn-script.c

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

DEFINITIONS

This source file includes following definitions.
  1. main

   1 /* Test of posix_spawn() function.
   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.h>
  20 
  21 #include <errno.h>
  22 #include <fcntl.h>
  23 #include <stdio.h>
  24 #include <string.h>
  25 #include <unistd.h>
  26 #include <sys/types.h>
  27 #include <sys/wait.h>
  28 
  29 #include "macros.h"
  30 
  31 #define DATA_FILENAME "test-posix_spawn-script.tmp"
  32 
  33 int
  34 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36   unlink (DATA_FILENAME);
  37 
  38   /* Check an invocation of an executable script.
  39      This should only be supported if the script has a '#!' marker; otherwise
  40      it is unsecure: <https://sourceware.org/bugzilla/show_bug.cgi?id=13134>.
  41      POSIX says that the execlp() and execvp() functions support executing
  42      shell scripts
  43      <https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html>,
  44      but this is considered an antiquated feature.  */
  45   pid_t child;
  46 
  47   posix_spawn_file_actions_t actions;
  48   ASSERT (posix_spawn_file_actions_init (&actions) == 0);
  49   ASSERT (posix_spawn_file_actions_addopen (&actions, STDOUT_FILENO,
  50                                             DATA_FILENAME,
  51                                             O_RDWR | O_CREAT | O_TRUNC, 0600)
  52           == 0);
  53 
  54   {
  55     size_t i;
  56 
  57     for (i = 0; i < 2; i++)
  58       {
  59         const char *prog_path =
  60           (i == 0 ? SRCDIR "executable-script" : SRCDIR "executable-script.sh");
  61         const char *prog_argv[2] = { prog_path, NULL };
  62 
  63         int err = posix_spawn (&child, prog_path, &actions, NULL,
  64                                (char **) prog_argv, environ);
  65         if (err != ENOEXEC)
  66           {
  67             if (err != 0)
  68               {
  69                 errno = err;
  70                 perror ("posix_spawn");
  71                 return 1;
  72               }
  73 
  74             /* Wait for child.  */
  75             int status = 0;
  76             while (waitpid (child, &status, 0) != child)
  77               ;
  78             if (!WIFEXITED (status))
  79               {
  80                 fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
  81                 return 1;
  82               }
  83             int exitstatus = WEXITSTATUS (status);
  84             if (exitstatus != 127)
  85               {
  86                 fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
  87                 return 1;
  88               }
  89           }
  90       }
  91   }
  92 
  93 #if defined _WIN32 && !defined __CYGWIN__
  94   /* On native Windows, scripts - even with '#!' marker - are not executable.
  95      Only .bat and .cmd files are.  */
  96   fprintf (stderr, "Skipping test: scripts are not executable on this platform.\n");
  97   return 77;
  98 #else
  99   {
 100     const char *prog_path = SRCDIR "executable-shell-script";
 101     const char *prog_argv[2] = { prog_path, NULL };
 102 
 103     int err = posix_spawn (&child, prog_path, &actions, NULL,
 104                            (char **) prog_argv, environ);
 105     if (err != 0)
 106       {
 107         errno = err;
 108         perror ("posix_spawn");
 109         return 1;
 110       }
 111 
 112     posix_spawn_file_actions_destroy (&actions);
 113 
 114     /* Wait for child.  */
 115     int status = 0;
 116     while (waitpid (child, &status, 0) != child)
 117       ;
 118     if (!WIFEXITED (status))
 119       {
 120         fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
 121         return 1;
 122       }
 123     int exitstatus = WEXITSTATUS (status);
 124     if (exitstatus != 0)
 125       {
 126         fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
 127         return 1;
 128       }
 129 
 130     /* Check the contents of the data file.  */
 131     FILE *fp = fopen (DATA_FILENAME, "rb");
 132     if (fp == NULL)
 133       {
 134         perror ("cannot open data file");
 135         return 1;
 136       }
 137     char buf[1024];
 138     int nread = fread (buf, 1, sizeof (buf), fp);
 139     if (!(nread == 11 && memcmp (buf, "Halle Potta", 11) == 0))
 140       {
 141         fprintf (stderr, "data file wrong: has %d bytes, expected %d bytes\n", nread, 11);
 142         return 1;
 143       }
 144     if (fclose (fp))
 145       {
 146         perror ("cannot close data file");
 147         return 1;
 148       }
 149   }
 150 #endif
 151 
 152   /* Clean up data file.  */
 153   unlink (DATA_FILENAME);
 154 
 155   return 0;
 156 }

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