Accessing environment variable in a fastcgi application - c++

I have writen a fastcGI application using C and C++
I have a free function that returns a string, if a specific environment variable has not been set. The function looks like this:
namespace
{
std::string getNameString()
{
char * datastr_ = getenv(MY_ENVAR.c_str());
if (datastr_)
return std::string(datastr_);
return DEFAULT_NAME;
}
};
I then carry out the following steps (in the order given below)
I have edited my /etc/environment and added the appropriate environment variable
I confirm that the variable has been set by typing printenv on the console
I stop and then start the apache daemon
When I debug my application, I find that the environment variable has not been set. I suspect that the environment under which the fastcgi application is running may different from the environment 'normal' applications run under.
Does anyone know how to retrieve environment variable in a fastcgi app?

I suspect that fastcgi processes are spawned in a "cleaned" environment by default, given your observations. Apache certainly provides a way of setting environment variables for fastcgi. This has the added bonus of being slightly less cryptic too (who expects a webservice to behave differently when /etc/environment is changed?), like this you keep "web config things" with "web config things".

You could look here http://httpd.apache.org/docs/current/env.html and try to set the env variable in the apache process. I have assumed latest apache version.

Related

Set current user environment variable from c++ code visible to other process like cmds

I need to set a local environment variable for current user and it shoukd be visible to other processes like a new command prompt. I need it for windows. I have tried options like putenv and editing the registry from C++ code but the new cmd prompt see the old values. Primarily i need to edit PATH variable along with few custom env variables. Will appreciate if i can get a working sample code.
Please note that the environment variable need to persist past program execution.
My requirement is for windows. I even tried running setx from C++ code and it works fine but for PATH variable it trims it down to 1024 character and i lose the update. Is there a workaround to this?
IF my wording looks confusing about the requirement. I need exactly same behavior as if i am using setx.
Thanks in advance.
If you start Cmd.exe from your process you can control its environment. The environment variables are inherited from the parent process. They can also be overridden when you call CreateProcess.
If you change the users/system environment configuration in the registry(HKCU\Environment/HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment) and log off/reboot then the first process will use these new defaults.
If you update the registry you can tell other applications to refresh their environments without logging off by broadcasting a message:
BroadcastSystemMessage(0, 0, WM_SETTINGCHANGE, 0, (LPARAM)TEXT("Environment"));
In reality it is only Explorer.exe that reacts to this message but that is enough to affect new applications started from the taskbar/start menu.
The setx command is actually an executable that sets values in the registry. If you are looking to simulate the behavior where you can set an environment variable that will last longer than the current process you will need to write it to the HKCU\Environment key. The HKCU is for the the current user and can be written to without elevated permissions.
Use RegEdit.exe or reg.exe query HKCU\Environment to view the current settings. From C/C++ you can use the Registry functions. If you can, I recommend using the ATL CRegKey class as it follows RAII and ensures handles are properly cleaned up.

Creating a C++ daemon and keeping the environment

I am trying to create a c++ daemon that runs on a Red Hat 6.3 platform and am having trouble understanding the differences between the libc daemon() call, the daemon shell command, startproc, start-stop-daemon and about half a dozen other methods that google suggests for creating daemons.
I have seen suggestions that two forks are needed, but calling daemon only does one. Why is the second fork needed?
If I write the init.d script to call bash daemon, does the c code still need to call daemon?
I implemented my application to call the c daemon() function since it seems the simplest solution, but I am running into the problem of my environment variables seem to get discarded. How do I prevent this?
I also need to run the daemon as a particular user, not as root.
What is the simplest way to create a C++ daemon that keeps its environment variables, runs as a specific user, and is started on system boot?
Why is the second fork needed?
Answered in What is the reason for performing a double fork when creating a daemon?
bash daemon shell command
My bash 4.2 does not have a builtin command named daemon. Are you sure yours is from bash? What version, what distribution?
environment variables seem to get discarded.
I can see no indication to that effect in the documentation. Are you sure it is due to daemon? Have you checked whether they are present before, and missing after that call?
run the daemon as a particular user
Read about setresuid and related functions.
What is the simplest way to create a C++ daemon that keeps its environment variables, runs as a specific user, and is started on system boot?
Depends. If you want to keep your code simple, forget about all of this and let the init script do this via e.g. start-stop-daemon. If you want to handle this in your app, daemon combined with retresuid should be a good approach, although not the only one.

In Linux C++, how do you read an environment variable of a specified user?

I know that getenv() returns a value of specified environment variable of the current user, but my code requires root privileges so getenv() would only use the sudo environment variables. I also know that SUDO_USER tells which user is invoking sudo, which is the user environment I want use for getenv().
char* gnome_env_var = getenv("GDMSESSION"); //returns null as not found in sudo env
char* usr = getenv("SUDO_USER");
Is there a way I can get the value of an environment variable for the logged in user, not the sudo environment?
EDIT
Okay, so what I'm hearing is that the set of environment variables are unique to each process, not user and using sudo to invoke a process with root privileges calls execve which can create an entirely new set of environment variables for that process. So to rephrase, is there a way besides messing with the sudoers file, and within the current process, of finding the calling process's environment variables?
I particularly need the GDMSession environment variable.
getenv doesn't tell you about the environment variables of the current user, but the current process. Users are free to have as many environments as they want(and can create processes), for example with the export shell built-in. In every call to execve, the calling program is free to create an entirely new environment for the executed process.
Therefore, there is no way to get the environment variables of the user, or even those of the process executing sudo. Why do you want that anyways?
You can, however, configure sudo to keep some or all environment variables, via the keep_env and reset_env directives in /etc/sudoers.
There isn't a "user environment." Every process has its own copy of the environment variables. They don't even automatically inherit -- that they appear to is an illusion maintained by the shell and the C library. It is more accurate to think of them as a second set of command line arguments to every program.
So before we can answer your question, you need to clear up what you mean! There are possibilities - none of them are elegant, mind, but they do exist - but they depend crucially on which environment variable you want to get at in which process's state and why.

C++ getenv always returns null value

I have just added the environment variable "DataDir", but the getenv function still returns null value.
Here is my code:
const char *ret = getenv("DataDir");
I restarted my computer and it done.
did you remember to export the variable before running the program? If you are using bash shell on linux, for example, you generally should use export DataDir="..."
On windows, if you set the environment variables using the system settings window, it will not immediately propagate to all of the running programs. If "I restarted my computer and it done." means "restarting the computer resolved the issue", then I believe that explains the problem. After changing the environment variable, try closing all programs and then start a CMD session (or visual studio) and run the program again
Are you running on Windows? Did you set the environment variable through the control panel? If so, that only affects processes that you start (programs that you launch) after you changed the setting. If you're running from a command prompt, and the command prompt didn't inherit the new environment variable, then your program won't inherit it either.
After rebooting, all new processes inherit the new environment variable.
On the other hand, if you set the variable and then run the program:
C:\>set DataDir=blah
C:\>.\my_program
then your program will inherit the variable (but it won't persist across a reboot).
Similar considerations apply on Linux and other systems, but the details differ.
Note that I'm only guessing, based on the symptoms you reported, what system you're using. In the future, it would be helpful to provide that information in the question (if it's not relevant we can ignore it).

How to get environment variable from FastCGI C++ binary during startup

I have a FastCGI application that loads and processes a lot of data during its startup. And I want it to get some environment variable to determine its input data path, but as much as I understand so far, environment pointer envp comes with the request.
I want to do getenv before the very first request, say directly after FCGX_Init(). Is it possible?
Yeah, as it turnes out, the lighttpd's counterpart to -initial-env is "bin-environment" array in the fastcgi.server section of lighttpd.conf. The values defined there are accessible for getenv() from the very beginning of execution.