- 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