(root)/
glibc-2.38/
posix/
tst-execvpe5.c
       1  /* General tests for execpve.
       2     Copyright (C) 2016-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <fcntl.h>
      21  #include <stdlib.h>
      22  #include <string.h>
      23  #include <unistd.h>
      24  #include <wait.h>
      25  
      26  
      27  /* Nonzero if the program gets called via `exec'.  */
      28  static int restart;
      29  
      30  
      31  #define CMDLINE_OPTIONS \
      32    { "restart", no_argument, &restart, 1 },
      33  
      34  /* Prototype for our test function.  */
      35  extern void do_prepare (int argc, char *argv[]);
      36  extern int do_test (int argc, char *argv[]);
      37  
      38  #include "../test-skeleton.c"
      39  
      40  #define EXECVPE_KEY    "EXECVPE_ENV"
      41  #define EXECVPE_VALUE  "execvpe_test"
      42  
      43  
      44  static int
      45  handle_restart (void)
      46  {
      47    /* First check if only one variable is passed on execvpe.  */
      48    int env_count = 0;
      49    for (char **e = environ; *e != NULL; ++e)
      50      if (++env_count == INT_MAX)
      51        {
      52  	printf ("Environment variable number overflow");
      53  	exit (EXIT_FAILURE);
      54        }
      55    if (env_count != 1)
      56      {
      57        printf ("Wrong number of environment variables");
      58        exit (EXIT_FAILURE);
      59      }
      60  
      61    /* Check if the combinarion os "EXECVPE_ENV=execvpe_test"  */
      62    const char *env = getenv (EXECVPE_KEY);
      63    if (env == NULL)
      64      {
      65        printf ("Test environment variable not found");
      66        exit (EXIT_FAILURE);
      67      }
      68  
      69    if (strncmp (env, EXECVPE_VALUE, sizeof (EXECVPE_VALUE)))
      70      {
      71        printf ("Test environment variable with wrong value");
      72        exit (EXIT_FAILURE);
      73      }
      74  
      75    return 0;
      76  }
      77  
      78  
      79  int
      80  do_test (int argc, char *argv[])
      81  {
      82    pid_t pid;
      83    int status;
      84  
      85    /* We must have
      86       - one or four parameters left if called initially
      87         + path for ld.so		optional
      88         + "--library-path"	optional
      89         + the library path	optional
      90         + the application name
      91  
      92      if --enable-hardcoded-path-in-tests is used, just
      93        + the application name
      94    */
      95  
      96    if (restart)
      97      {
      98        if (argc != 1)
      99  	{
     100  	  printf ("Wrong number of arguments (%d) in restart\n", argc);
     101  	  exit (EXIT_FAILURE);
     102  	}
     103  
     104        return handle_restart ();
     105      }
     106  
     107    if (argc != 2 && argc != 5)
     108      {
     109        printf ("Wrong number of arguments (%d)\n", argc);
     110        exit (EXIT_FAILURE);
     111      }
     112  
     113    /* We want to test the `execvpe' function.  To do this we restart the
     114       program with an additional parameter.  */
     115    pid = fork ();
     116    if (pid == 0)
     117      {
     118        /* This is the child.  Construct the command line.  */
     119  
     120        /* We cast here to char* because the test itself does not modify neither
     121  	 the argument nor the environment list.  */
     122        char *envs[] = { (char*)(EXECVPE_KEY "=" EXECVPE_VALUE), NULL };
     123        if (argc == 5)
     124  	{
     125  	  char *args[] = { argv[1], argv[2], argv[3], argv[4],
     126  			   (char *) "--direct", (char *) "--restart", NULL };
     127  	  execvpe (args[0], args, envs);
     128  	}
     129        else
     130  	{
     131  	  char *args[] = { argv[0],
     132  			   (char *) "--direct", (char *) "--restart", NULL };
     133  	  execvpe (args[0], args, envs);
     134  	}
     135  
     136        puts ("Cannot exec");
     137        exit (EXIT_FAILURE);
     138      }
     139    else if (pid == (pid_t) -1)
     140      {
     141        puts ("Cannot fork");
     142        return 1;
     143      }
     144  
     145    /* Wait for the child.  */
     146    if (waitpid (pid, &status, 0) != pid)
     147      {
     148        puts ("Wrong child");
     149        return 1;
     150      }
     151  
     152    if (WTERMSIG (status) != 0)
     153      {
     154        puts ("Child terminated incorrectly");
     155        return 1;
     156      }
     157    status = WEXITSTATUS (status);
     158  
     159    return status;
     160  }