(root)/
glibc-2.38/
stdlib/
tst-environ.c
       1  /* Copyright (C) 1999-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library 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 GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <stdio.h>
      20  #include <stdlib.h>
      21  #include <string.h>
      22  #include <libc-diag.h>
      23  
      24  #define VAR "FOOBAR"
      25  
      26  char putenv_val[100] = VAR "=some longer value";
      27  
      28  static int
      29  do_test (void)
      30  {
      31    int result = 0;
      32    const char *valp;
      33  
      34    /* First test: remove entry FOOBAR, whether it exists or not.  */
      35    unsetenv (VAR);
      36  
      37    /* Now getting the value should fail.  */
      38    if (getenv (VAR) != NULL)
      39      {
      40        printf ("There should be no `%s' value\n", VAR);
      41        result = 1;
      42      }
      43  
      44    /* Now add a value, with the replace flag cleared.  */
      45    if (setenv (VAR, "one", 0) != 0)
      46      {
      47        printf ("setenv #1 failed: %m\n");
      48        result = 1;
      49      }
      50  
      51    /* Getting this value should now be possible.  */
      52    valp = getenv (VAR);
      53    if (valp == NULL || strcmp (valp, "one") != 0)
      54      {
      55        puts ("getenv #2 failed");
      56        result = 1;
      57      }
      58  
      59    /* Try to replace without the replace flag set.  This should fail.  */
      60    if (setenv (VAR, "two", 0) != 0)
      61      {
      62        printf ("setenv #2 failed: %m\n");
      63        result = 1;
      64      }
      65  
      66    /* The value shouldn't have changed.  */
      67    valp = getenv (VAR);
      68    if (valp == NULL || strcmp (valp, "one") != 0)
      69      {
      70        puts ("getenv #3 failed");
      71        result = 1;
      72      }
      73  
      74    /* Now replace the value using putenv.  */
      75    if (putenv (putenv_val) != 0)
      76      {
      77        printf ("putenv #1 failed: %m\n");
      78        result = 1;
      79      }
      80  
      81    /* The value should have changed now.  */
      82    valp = getenv (VAR);
      83    if (valp == NULL || strcmp (valp, "some longer value") != 0)
      84      {
      85        printf ("getenv #4 failed (is \"%s\")\n", valp);
      86        result = 1;
      87      }
      88  
      89    /* Now one tricky check: changing the variable passed in putenv should
      90       change the environment.  */
      91    strcpy (&putenv_val[sizeof VAR], "a short one");
      92  
      93    /* The value should have changed again.  */
      94    valp = getenv (VAR);
      95    if (valp == NULL || strcmp (valp, "a short one") != 0)
      96      {
      97        puts ("getenv #5 failed");
      98        result = 1;
      99      }
     100  
     101    /* It should even be possible to rename the variable.  */
     102    strcpy (putenv_val, "XYZZY=some other value");
     103  
     104    /* Now a lookup using the old name should fail.  */
     105    if (getenv (VAR) != NULL)
     106      {
     107        puts ("getenv #6 failed");
     108        result = 1;
     109      }
     110  
     111    /* But using the new name it should work.  */
     112    valp = getenv ("XYZZY");
     113    if (valp == NULL || strcmp (valp, "some other value") != 0)
     114      {
     115        puts ("getenv #7 failed");
     116        result = 1;
     117      }
     118  
     119    /* Create a new variable with the old name.  */
     120    if (setenv (VAR, "a new value", 0) != 0)
     121      {
     122        printf ("setenv #3 failed: %m\n");
     123        result = 1;
     124      }
     125  
     126    /* At this point a getenv call must return the new value.  */
     127    valp = getenv (VAR);
     128    if (valp == NULL || strcmp (valp, "a new value") != 0)
     129      {
     130        puts ("getenv #8 failed");
     131        result = 1;
     132      }
     133  
     134    /* Black magic: rename the variable we added using putenv back.  */
     135    strcpy (putenv_val, VAR "=old name new value");
     136  
     137    /* This is interesting.  We have two variables with the same name.
     138       Getting a value should return one of them.  */
     139    valp = getenv (VAR);
     140    if (valp == NULL
     141        || (strcmp (valp, "a new value") != 0
     142  	  && strcmp (valp, "old name new value") != 0))
     143      {
     144        puts ("getenv #9 failed");
     145        result = 1;
     146      }
     147  
     148    /* More fun ahead: we are now removing the variable.  This should remove
     149       both values.  The cast is ok: this call should never put the string
     150       in the environment and it should never modify it.  */
     151    putenv ((char *) VAR);
     152  
     153    /* Getting the value should now fail.  */
     154    if (getenv (VAR) != NULL)
     155      {
     156        printf ("getenv #10 failed (\"%s\" found)\n", getenv (VAR));
     157        result = 1;
     158      }
     159  
     160    /* Now a test with an environment variable that's one character long.
     161       This is to test a special case in the getenv implementation.  */
     162    strcpy (putenv_val, "X=one character test");
     163    if (putenv (putenv_val) != 0)
     164      {
     165        printf ("putenv #2 failed: %m\n");
     166        result = 1;
     167      }
     168  
     169    valp = getenv ("X");
     170    if (valp == NULL || strcmp (valp, "one character test") != 0)
     171      {
     172        puts ("getenv #11 failed");
     173        result = 1;
     174      }
     175  
     176    /* Both setenv and unsetenv should return -1/EINVAL for NULL or "" name
     177       or if name contains '=' character.  */
     178    errno = 0;
     179    if (setenv (NULL, "val", 1) >= 0 || errno != EINVAL)
     180      {
     181        puts ("setenv #4 failed");
     182        result = 1;
     183      }
     184  
     185    errno = 0;
     186    if (setenv ("", "val", 0) >= 0 || errno != EINVAL)
     187      {
     188        puts ("setenv #5 failed");
     189        result = 1;
     190      }
     191  
     192    errno = 0;
     193    if (setenv ("var=val", "val", 1) >= 0 || errno != EINVAL)
     194      {
     195        puts ("setenv #6 failed");
     196        result = 1;
     197      }
     198  
     199    /* This deliberately tests supplying a null pointer to a function whose
     200       argument is marked __attribute__ ((nonnull)). */
     201    DIAG_PUSH_NEEDS_COMMENT;
     202    DIAG_IGNORE_NEEDS_COMMENT(5, "-Wnonnull");
     203    errno = 0;
     204    if (unsetenv (NULL) >= 0 || errno != EINVAL)
     205      {
     206        puts ("unsetenv #1 failed");
     207        result = 1;
     208      }
     209    DIAG_POP_NEEDS_COMMENT;
     210  
     211    errno = 0;
     212    if (unsetenv ("") >= 0 || errno != EINVAL)
     213      {
     214        puts ("unsetenv #2 failed");
     215        result = 1;
     216      }
     217  
     218    errno = 0;
     219    if (unsetenv ("x=y") >= 0 || errno != EINVAL)
     220      {
     221        puts ("unsetenv #3 failed");
     222        result = 1;
     223      }
     224  
     225    return result;
     226  }
     227  
     228  #define TEST_FUNCTION do_test ()
     229  #include "../test-skeleton.c"