- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi All I am facing issue in setting environment variable in the linux platform using a fortran code.I have tried with SETENVQQ and export command inside the SYSTEM function and EXECUTE_COMMAND_LINE function.Please help me to solve this issue. Thanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I assume the interest is in altering an environment variable in the underlying shell under which the Fortran program is running. If so then SYSTEM and EXECUTE_COMMAND_LINE would not be applicable as those affect a separate instance of a shell spawned for the former, and the local context of spawned processes for the latter.
If you can share your source code with us for the SETENVQQ method then we would be able to help get that working for you.
Here is a quick (and not so pretty) example borrowing example code from the Fortran User's Guide from SETENVQQ, GET_ENVIRONMENT_VARIABLE, and .EXECUTE_COMMAND_LINE.
program env_example implicit none call my_setenvqq call my_execute_command_line end program env_example subroutine my_setenvqq USE IFPORT implicit none character name*20 logical(4) success success = SETENVQQ("PATH=c:\mydir\tmp") name='PATH' call my_getenv(name) end subroutine my_setenvqq subroutine my_execute_command_line implicit none integer :: CSTAT, ESTAT character(100) :: CMSG character name*20 call EXECUTE_COMMAND_LINE ("export LIB=/mydir2/tmp;echo ' LIB is: '$LIB", & & EXITSTAT=ESTAT, CMDSTAT=CSTAT, CMDMSG=CMSG) if (CSTAT > 0) then print *, "Command execution failed with error ", TRIM(CMSG) else if (CSTAT < 0) then print *, "Command execution not supported" else print *, "Command completed with status ", ESTAT end if name='LIB' call my_getenv(name) end subroutine my_execute_command_line subroutine my_getenv(name) implicit none character name*20, val*40 integer len, status call get_environment_variable (name, val, len, status, .true.) if (status .ge. 2) then write (*,*) 'get_environment_variable failed: status = ', status stop end if if (status .eq. 1) then write (*,*) 'env var does not exist' stop end if if (status .eq. -1) then write (*,*) 'env var length = ', len, ' truncated to 40' len = 40 end if if (len .eq. 0) then write (*,*) 'env var exists but has no value' stop end if write (*,*) 'env var value = ', val (1:len) end subroutine my_getenv
$ ifort -V Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 16.0.0.109 Build 20150815 Copyright (C) 1985-2015 Intel Corporation. All rights reserved. $ ifort u594761.f90 ; ./a.out env var value = c:\mydir\tmp LIB is: /mydir2/tmp Command completed with status 0 env var does not exist
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you want to stick to the standard and avoid using extensions that are dependent on the compiler, you could employ C bindings to call a C function that sets the environment variable.
Take a look at the sample codes:
#include <stdlib.h> void set_ev() { setenv("MY_ENV_VAR", "Hey, what's up!",1); }
------------------------------------------------------------------------------------------------------
program tes_set_ev use, intrinsic :: iso_c_binding implicit none character(len= 50) :: sys_ev INTERFACE subroutine set_ev() bind(c) end subroutine set_ev END INTERFACE ! call get_environment_variable('MY_ENV_VAR', sys_ev) print*, 'Before calling c void: ->|'//trim(sys_ev)//'|<-' call set_ev() call get_environment_variable('MY_ENV_VAR', sys_ev) print*, 'After calling c void: ->|'//trim(sys_ev)//'|<-' end program tes_set_ev
-------------------------------------------------------------------------------------------------------------------
This is the compilation lines and the output:
$>gcc -c set_ev.c $>ifort tes_set_ev.f90 set_ev.o -o tes_set_ev $>./tes_set_ev Before calling c void: ->||<- After calling c void: ->|Hey, what's up!|<-
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Why not
INTERFACE function setenv(name,value,overwrite) bind(C,name='setenv') use ISO_C_BINDING implicit none integer(C_INT) setenv character(KIND=C_CHAR), intent(in) :: name(*) character(KIND=C_CHAR), intent(in) :: value(*) integer(C_INT), value :: overwrite end function setenv END INTERFACE
and then invoke setenv() directly?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Repeat Offender wrote:
Why not
INTERFACE function setenv(name,value,overwrite) bind(C,name='setenv') use ISO_C_BINDING implicit none integer(C_INT) setenv character(KIND=C_CHAR), intent(in) :: name(*) character(KIND=C_CHAR), intent(in) :: value(*) integer(C_INT), value :: overwrite end function setenv END INTERFACEand then invoke setenv() directly?
I guess, you would have to make sure then, that you pass a proper '\0' terminated string, when calling from Fortran, otherwise C would have problem to detect, where the string ends.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yep. Instead of passing "MY_ENV_VAR", one would pass 'MY_ENV_VAR'//C_NULL_CHAR or 'MY_ENV_VAR'//ACHAR(0). Normal stuff encountered when doing C interoperability. This is more commonplace in Windows where users seem to invoke Win32 API functions on more of a routine basis.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page