Web lists-archives.com

Re: [Mingw-users] setenv()




-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 15/11/16 21:46, Anton Shepelev wrote:
> Is  the  setenv() function from stdlib.h supposed to work in
> MinGW?

Short answer: no.

Explanation:

1) MSVCRT.DLL exports putenv(), (strictly _putenv(), but MinGW defines
   an import library alias with the POSIX.1-2008-XSI compatible name),
   which is semantically similar to the Unix System V function of the
   same name.  However, there is no setenv(), nor any semantically
   similar API, provided by any Windows DLL.

2) Neither putenv(), nor setenv() is required by ISO-C, so, even
   though both are specified by POSIX, it isn't considered imperative
   for MinGW to provide what isn't already provided by MSVCRT.DLL.

> When I compile the following  program:
> 
> #include <stdlib.h> int main( int argc, char** argv ) {
> setenv("test", "1", 1); return 0; }
> 
> I get:
> 
> cco6C8tG.o:test.c:(.text+0x26): undefined reference to `setenv' 
> collect2.exe: error: ld returned 1 exit status

Expected.  C generates an implicit function prototype, at compile time,
but fails at link time, because no such API is available.  There are
two possible solutions, which you could consider:

1) Modify your source, as Eli has suggested, to use [_]putenv()

2) Draw inspiration from the attached modification to your original
   sample code, to implement setenv(), (or, if you raise a feature
   request on the issue tracker, I may consider adding it for the
   next mingwrt release).

> If [I] change the file extension to cpp, the error is different:
> 
> test.cpp: In function 'int main(int, char**)': test.cpp:3:24:
> error: 'setenv' was not declared in this scope { setenv("test",
> "1", 1);

Again, expected; because setenv() is not implemented, <stdlib.h> does
not furnish a prototype, and you're now compiling as C++, which MUST
have a declaration in scope at compile time ... C++ will NOT infer one
implicitly, so this becomes a compile time failure.

> And where is stdlib.h located?  I couldn't discover it using:
> 
> find / -name stdlib.h

Strange; if you have mingwrt properly installed, (as it MUST be for GCC
to work at all), it should be in $MINGW_ROOT/include, (where $MINGW_ROOT
represents the root of your installation tree ... gcc.exe itself will be
installed as $MINGW_ROOT/bin/gcc.exe

- -- 
Regards,
Keith.

Public key available from keys.gnupg.net
Key fingerprint: C19E C018 1547 DE50 E1D4 8F53 C0AD 36C6 347E 5A3F
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.20 (GNU/Linux)

iQIcBAEBAgAGBQJYLHOAAAoJEMCtNsY0flo/vmMQAIx4dZkut0wxu5RFHxHhmZ0Y
LPvK+6K3veLlRceX/KSXAtno4mp3tWGT50OUwAmB3VyJ6SHJvuFg9cL+P6fqC0/j
mO976093wpUerrk1QBpC9J1lZVYSRkSpD4MHfKrhQ5SRc9ifaDog06PbLYBOG7Q5
fpc/C893ZL49yqni7D6W6KvVZyTtcyA4tyCdQY99bqnGSdZArck3hkqKZq6EhwH0
6UyDMgZgRucXqWYy/XZxg2kfpDsuWrNzELFk/wSLcSGTdLDnjTpV/PuFV+HR+d8h
i1wHShyfcuAUKpCg7vp75yH+BgpiVWBnwHA1P9mabkKAJYQly3dOFn0UIuJ/MstC
IQoBrmAili6dnp/ADtLP9aI87wRd9XckeuPAmL0MAYqKQQqys1IBbMAnqGsTpZN1
pPsDLlE2+LZFwiFxkkJHr7n3EOekweDF+gE/NzRu6dlf0cyMFjMzQe5DpYjcTpEK
prtaXNljomyP63QS/CIqonSyhRol4fxt4Pahd9mw1OQu1LLLjB4XA7eKs6b6whRz
sVwa/tyKAXl7C/QabNWWrzozo8ilZjvt0ht3HtPEIW6RQa2pmkj4lG1mm8vUnofb
c7i6n94PTqzf7HNvSea9Df2hRWU4nTV05JaEyFtS1KJ6HI4p4iKJAYSogvmEZa+Q
k7zQSvZVJP/nF+4wCmgZ
=9MLd
-----END PGP SIGNATURE-----
#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

_EXTERN_C int setenv( const char *, const char *, int );

int setenv( const char *var, const char *value, int overwrite )
{
  int retval = -1;
  if( var && *var && (strchr( var, '=' ) == NULL) )
  {
    if( overwrite || getenv( var ) == NULL )
    {
      const char *fmt = "%s=%s";
      char buf[1 + snprintf( NULL, 0, fmt, var, value )];
      snprintf( buf, sizeof( buf ), fmt, var, value );
      if( (retval = putenv( buf )) == 0 )
	printf( "%1$s buffer assigned at %1$#08x\n", buf );
      else
        errno = ENOMEM;
    }
    else
      retval = 0;
  }
  else
    errno = EINVAL;
  return retval;
}

int main( int argc, char** argv )
{
  const char *envval;
  setenv("test", "1", 1);
  if( (envval = getenv( "test" )) != NULL )
    printf( "envval 'test' retrieved at %1$#08x; value = %1$s\n", envval );
  return 0;
}
------------------------------------------------------------------------------
_______________________________________________
MinGW-users mailing list
MinGW-users@xxxxxxxxxxxxxxxxxxxxx

This list observes the Etiquette found at 
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Also: mailto:mingw-users-request@xxxxxxxxxxxxxxxxxxxxx?subject=unsubscribe