getenv() does not return last backslash - c++

I am trying to read a env variable using getenv() in C++,
lets say env variable is
CONTENT_PATH=C:\Users\rat\Documents\fix\plat\gen\content\
It is being set by a batch file before program runs, contents of batch file.
set mypath=%~dp0
set gameContent=%mypath%plat\gen\content\
:: setting CONTENT_PATH
setx -m CONTENT_PATH "%gameContent%"
during debugging in visual studio, I am getting value as
C:\Users\rat\Documents\fix\plat\gen\content"
the last '\' is not coming, even though if I manually set the env variable value using Control Panel->Advance system settings.

Related

Show environment variable LD_LIBRARY_PATH

I have simple console application that prints environment variables:
int main(int argc, char **argv, char **envp)
{
printf("Scanning for LD_LIB_PATH\n");
for (char **env = envp; *env != 0; env++)
{
char *thisEnv = *env;
std::string s= *env;
if (s.find("LD_LIBRARY_PATH")!=std::string::npos)
{
printf("!!!!!!! %s\n", thisEnv);
}
printf("%s\n", thisEnv);
}
}
Before run executable I run script that sets LD_LIBRARY_PATH
export LD_LIBRARY_PATH=~/aaa/bbb/Debug:~/ccc/ddd/Debug
echo "searching:"
export | grep LD_LIBRARY
echo "done"
Script run fine with output:
exporting
searching:
declare -x LD_LIBRARY_PATH="/home/vicp/aaa/bbb/Debug:/home/vico/ccc/ddd/Debug"
done
I run executable and it finds many variables but no environment variable LD_LIB_PATH. Why?
UPD
As recommended I script . ./script.sh
Then double check with command:
export |grep LD_LIBRARY_PATH
Got output:
declare -x LD_LIBRARY_PATH="/home/vicp/aaa/bbb/Debug:/home/vico/ccc/ddd/Debug"
But still don't see LD_LIBRARY_PATH in my programm.
Depending on how you run the script, the env variable will only be added to the environment of the subshell running the script.
If you run the script like this:
$ ./script.sh
This will spawn a new shell wherein the script is run. The parent shell, i.e. the one you started the script from, will not be affected by what the script does. Changes to the environment will therefore not be visible (changing the working directory or similar will also not work).
If the script is intended to modify the environment of the current shell, the script needs to be sourced using the . or source commands:
$ . ./script.sh
$ source ./script.sh
From help source in bash:
Execute commands from a file in the current shell.
Then there seems to be a problem with the code:
As a commenter stated previousy, there are a lot of exclamation points in the success case printf. I presume these were meant to highlight the found variable name. Since they are outside of the opening quote of the format string, they are interpreted as logical not operators.
The result is that the format string literal (a pointer) is negated, resulting in false due to the number of operators. This usually maps to 0, which would mean the format string becomes a null pointer. What happens when handing a null pointer to printf as the format string depends, as far as I can tell, on the implementation. If it doesn't crash, it most certainly will not print anything however.
So the code may actually work, but there is no visible output due to that bug. To fix it, move the exclamation points into the format string, i.e. after the opening quote.
Look at the line printf(!!!!!!!"%s\n", thisEnv);
Change to printf("!!!! %s\n", thisEnv);
It has nothing to do with your C/C++ application.
try the following:
$ ./script.sh
$ echo $LD_LIBRARY_PATH
And you'll see that LD_LIBRARY_PATH is not set
When you launch your script, bash creates a new process with its environment inherited from the original bash process. In that newly created process, you set the process environment variable LD_LIBRARY_PATH=xxxx
When finalized your script.sh exits, and its environment dies with it.
Meaning the LD_LIBRARY_PATH is not set in your original shell.
As mentioned here above you need to run your script in the current shell
Either with . or with source.
I tested with your C/C++ and it works

Reading user environment variables by os.environ

I have a setup script (not mine) which reads a certain system variable. I tried setting this in two ways:
Going to control panel > User Accounts > Change my environment variables
In command line: setx myvar myvalue
I set it as user variables, since i don't have the rights to set system variables. If i open a new command line window and type set, my variable shows there correctly.
However, if i start python and run the following script, i don't see my variable:
import os
print os.environ
I am using windows 10 and python 2.7. Modifying the code to get the variable is not possible since it is code from an external library.

C++ execute temp file as bash script

I have a program that needs to run a program we'll call externalProg in parallel on our linux (CentOS) cluster - or rather, it needs to run many instances of externalProg, each on different cores. Each "thread" creates 3 files based on a few parameters - the inputs to externalProg, a command file to tell externalProg how to execute my file, and a bash script to set up the environment (calls a setup script provided by the manufacturer) and actually call externalProg with my inputs.
Since this needs to be parallel with an unknown number of concurrent threads and I don't want to risk overwriting another thread's files, I am creating temp files using
mkstemp("PREFIX_XXXXXX")
for these input files. After the external program runs, I extract the relevant data and store it, and close the temp files (therefore deleting them).
We'll call the files created (Which actually have a name based on the template above)
tmpInputs - Inputs to externalProg
tmpCommand - Input that tells externalProg how to execute tmpInputs
tmpBash - bash script to set up and call externalProg with my inputs
The file tmpBash looks something like
source /path/to/setup/script # Sets up environment variables
externalProg < /path/to/tmpCommand
where tmpCommand is just a simple text file.
The problem I'm having is actually executing the bash script. Within my program, I call
ostringstream launchcmd;
launchcmd << "bash " << path_to_tmpBash
system(launchcmd.str().c_str());
But nothing happens. No error, no warning, no 'file not found' or permission denied or anything. I have verified that the files are being created and have the correct content. The rest of the code after system() is executed successfully (Though it fails since externalProg wasn't run).
Strangely, if I go back to the terminal and type
bash /path/to/tmpBash
then externalProg is executed successfully. I have also cout'd the launchcmd string, copy and pasted that in to the terminal, which also works successfully. For some reason, this only fails when called within my program.
After a bit of experimentation, I've determined that system() calls /bin/sh on our cluster. If I change launchcmd to look like
/path/to/tmpBash
(So that the full command should look like /bin/sh /path/to/tmpBash), I get a permission denied error, which is no surprise. The problem is that I can't chmod +x the tmpBash file while it's still open, and if I close the file, it gets deleted - so I'm not sure how to address that.
Is there something obviously wrong I'm doing, or does system() have some nuance that I'm missing?
edit: I wanted to add that I can successfully call things like
system("echo $PATH")
and get the expected results (in this case, my default $PATH).
Two separate ideas:
Change your SHELL environment variable to be /bin/bash, then call system(),
or:
Use execve directly `execve('/bin/bash', ['/path/to/tmpBash'], environ)

Passing the environment variables to the launched process bash script

Under linux, I have a bash script, that launches a c++ program binary.
What I need to do is set an environment variable in that script, and access that variable
inside the launched C++ program using getenv .
Here is the code for the script
#!/bin/bash
export SAMPLE_VAR=1
./c++_binary
The c++ program:
char * env_var = getenv("SAMPLE_VAR");
if (env_var != NULL) printf("var set\n");
However this does not seem to work. From what I understand is that when we execute the script, it will run in a new subshell and set the environment variable SAMPLE_BAR there, but the C++ binary is launched in the same subshell as well (may be I am wrong here) so it should have access to the SAMPLE_VAR. I even tried writing a separate script that just sets the env variable, and in the main script I called that script as source env_var_set.sh to no avail.
Is it possible to pass on a newly set environment variable to a program this way ?
Thanks
Since feature requests to mark a comment as an answer remain declined, I copy the above solution here.
Ah Sorry for the Typos, And my mistake, Inside the script I was launching the binary with 'sudo' which ran it in root's env and didnt have the variable set there. Removed sudo and it worked fine. Sorry for the confusion. Cheers. – Abdullah
First of all you need to source your shell script in order for the env variable to be set. and secondly include quotes in the getenv call.
char * env_var = getenv("SAMPLE_VAR");
if (env_var != NULL) printf("var set\n");

Using getenv function in Linux

I have this following simple program:
int main()
{
char* v = getenv("TEST_VAR");
cout << "v = " << (v==NULL ? "NULL" : v) << endl;
return 0;
}
These lines are added to .bashrc file:
TEST_VAR="2"
export TEST_VAR
Now, when I run this program from the terminal window (Ubuntu 10.04), it prints v = 2. If I run the program by another way: using launcher or from Eclipse, it prints NULL. I think this is because TEST_VAR is defined only inside bash shell. How can I create persistent Linux environment variable, which is accessible in any case?
On my system (Fedora 13) you can make system wide environment variables by adding them under /etc/profile.d/.
So for example if you add this to a file in /etc/profile.d/my_system_wide.sh
SYSTEM_WIDE="system wide"
export SYSTEM_WIDE
and then open a another terminal it should source it regardless of who the user is opening the terminal
echo $SYSTEM_WIDE
system_wide
Add that to .bash_profile (found in your home directory). You will need to log out and log back in for it to take effect.
Also, since you are using bash, you can combine the export and set in a single statement:
export TEST_VAR="2"
Sorry if I'm being naive but isn't .bash_profile useful only if you are running bash as your default shell ?
I 'sometimes' use Linux and mostly use ksh. I have .profile so may be you should check for .*profile and export the variable there.
Good luck :)
There is no such thing as a system-wide environment variable on Linux. Every process has its own environment. Now by default, every process inherits its environment from its parent, so you can get something like a system-wide environment by ensuring that a var is set in an ancestor of every process of interest. Then, as long as no other process changes that var, every process of interest will have it set.
The other answers here give various methods of setting variables early. For example, .bash_profile sets it in every login process a user runs, which is the ultimate parent of every process they run after login.
/etc/profile is read by every bash login by every user.