I was wondering if there is a way to set an environment variable from a bash process and read it from another.
As environment variables' values are local to processes (besides the inheritance), one can't just do export FOO="bar" in a terminal and read it from another.
I was then trying to get them through /proc/environ, but this is what I got:
etuardu#subranu:~$ FOO="foo" bash
etuardu#subranu:~$ strings /proc/$$/environ | grep FOO
FOO=foo
etuardu#subranu:~$ export FOO="bar"
etuardu#subranu:~$ strings /proc/$$/environ | grep FOO
FOO=foo
etuardu#subranu:~$ echo $FOO
bar
It seems I can just get the value that that environment variable had when the process started.
How about its current value?
This is not possible in general because of the way environment variables work.
When a process is first execed, the kernel supplies it with its initial set of environment variables together with some other stuff (mainly its argv vector, i.e. its command line). Thereafter, this list (like the argv vector) is just a regular C array of character pointers inside the process. The process is free to manage them however it likes, including completely recycling the memory that holds the strings for some other use if it wants to. It isn't safe for one process to go peeking inside any other process's memory space to find its environment variables.
Most types of processes do use the list of environment variables supplied by the kernel more or less as-is, perhaps querying it and modifying it with C library functions like getenv() and putenv(). If these processes run any other executables in their turn, they pass the same environment vector to the execve system call which they received at the start of their own execution, which means that the new executable gets the same environment (possibly enhanced by some calls to putenv()).
Shells are another matter. Because environment variables are so important in shell scripts, some shells use the environment vector supplied to them only as a "start value", and thereafter ignore it. They manage their environment variables using their own, more capable, data structures. When they execute child processes of their own, they pass a completely new environment vector to the new process, constructed from those internal data structures. This means that even if you were to peek into a shell's memory space to find its environment variables as suggested above, you would find only the initial set, not the environment that the shell is actually using!
What you might be able to do is query a process's initial set of environment variables, that is, the same vector that was passed to the executable when it started. But this is not portable, and there is considerable variation even among operating systems that support this. For example, in historical UNIXes, it is still a bit ugly because it still involves peeking into the process's memory space (albeit a special area of memory called the "user area"). Linux makes this possible more elegantly: the vector can be found as a text string in /proc/<pid>/environ. On most systems where it's possible to get this information, ps has an e option which is able to show it.
Related
I am running a local blastx server. One of the command line options is -num_threads. Looking at the executable, blastx, thinking it may be a shell script that sets OMP_NUM_THREADS, it turns out that it is in machine code. I am assuming (possibly incorrectly) that it is an OpenMP application and this got me thinking.
Question : is it possible to change the number of OpenMP threads as a command line option, as opposed to using the environmental variable OMP_NUM_THREADS?
Using OpenMP, you have basically 3 different ways of specifying the number of threads to use in a parallel region:
The most commonly used one is the environment variable OMP_NUM_THREADS which needs to be set in the code's environment prior to running it for being effective;
The function omp_set_num_threads(), to be called before reaching a parallel region; and
The optional num_threads() clause of the parallel directive.
The relative priorities of these are defined in great details by the standard but pretty much boil down to num_threads() taking precedence over omp_set_num_threads(), which itself takes precedence over OMP_NUM_THREADS.
So now, if you want to have your code defining the number of OpenMP threads to use as a command line option, what you need is:
To parse you command line, either by hand, or using a function like getopt, and to store the value you read in a variable; and
To use this value in either a call to omp_set_num_threads() or as a parameter to the num_threads() clause. Either of the two will take precedence to the possible value set for OMP_NUM_THREADS.
OMP_NUM_THREADS is parsed by the program at runtime, so it already does what you want.
Setting it at compile time has no effect (unless you specifically design your build system to use it).
Because you export this environment variable, it's there at runtime as well. That's why you think it is doing something when you compile.
I would like to know is there a way to export my shell variable to all sessions in the system (not only the current session). I'm not looking to set it in .bashrc file as the shell variable is a dynamic one it changes time to time.
You can set up your sessions to keep rereading a file on disk by setting a trap on DEBUG in your .bashrc:
trap 'source ~/.myvars' DEBUG
If you leave a terminal A open, run echo VAR=42 >> ~/.myvars in terminal B, then switch back to terminal A and echo $VAR, it'll "magically" be set.
You seem to misunderstand what export does. All it does is to move a local variable into the environment block within the process (/proc/$$/environ).
When a new process is created (a fork) then the program data areas, including the environment block, are copied to the new process (actually they are initially shared, then copied when one writes). When a different program is run (execve), by default the environment block remains from the previous program. See also the env(1) program.
So environment variables are normally inherited (copied) from their parent process. The only way to get a new environmnt variable into a running process is to use some sort of inoculation technique, as a debugger would do. Writing such a program is not an easy task, and I'm sure you could imagine the security implications.
You can't. A better explanation can be found in the unix stackexchange section here!
A shell variable probably is not suited for the use you are trying to achieve. Maybe you want to use files instead.
I have to find a button's name in a running process memory in Mac OSX and change it.
Supposing there is a "Test" application where it has a "Hello" button, is there any way to attach to "Test" application and change the "Hello!" button to "Bye!"?
I assume this could be done either using GDB or Xcode. If not, how can I do this?
Edit
Assuming you are really looking for dynamic data (as opposed to what your sample seemed to suggest :)) you could always just work with the debugger commands. This will require you to have a sense of the possible memory range to scan (or you'll simply get useless memory violations):
Use gdb commands, loop constructs and libc functions
# assume 0x1234 is a likely base address, say for the heap
(gdb) set $x=0x1234
(gdb) set $y = strdup("lookforthistext")
(gdb) while(0!=memcmp($x++, $y, 15) && $x<0x4321)
>end
(gdb) p $x
(gdb) x $x
This example scans the region 0x1234...0x4321 for the first match and prints/examines the output address.
You can use similar tricks (strncpy...?) to overwrite the memory if you had access to it.
Of course the program may fail dramatically if you do things like changing the length of a substring.. YMMV).
Consider saving your concocted commands as a script (turn on logging, use .gdbinit or even create gdb functions; sadly I know little about the latter)
Original answer:
You "need to"? I doubt it. Your best bet is to work with the windowing/UI API's of your operating system to retrieve the actual window that display the text and make it display another text (usually by sending it appropriate control messages). You'll need plenty of COW powers (think: root) to pull that off.
To answer the direct question:
Usually, messages like this are constants (static data) and as such are either
present in the data segment
read (memory mapped pages) from resources
Both of which are usually (these days at least) in read-only memory segments (think of sharing of memory mapped pages; this gives the kernel opportunity to share mapped regions of shared binary objects between processes - also it serves the obvious security purposes).
On the upside,
strings myprogram | grep 'Hello"
will tell you whether you can use sed, a hex editor or any other suitable editor to manipulate the binary even before it starts. There are two drawbacks I can think of here:
it is not dynamic (you can't have the text change on the fly)
it may break code signing (meaning the executable might get rejected by the OS because it has been modified).
When I execute environment commands, such as env, set, and unset, something happens, but what?
set hello='hello world!'
unset find
What do you do with the commands? Are the changes permanent or temporary? Where can you see the changes? I am an Ubuntu-newbie.
The changes are temporary. They persist only in the current shell. When you set an environment variable in your ~/.profile or ~/.bash_profile (just use the one that already exists, use ls -a ~ to see), they will be effectively permanent, as these files are "sourced" every time you open up a new shell.
For instance, if you added:
export HELLO="world"
To your ~/.profile, that variable would become available every time you open a new shell (you can refresh your current shell with source ~/.profile). You could test it with:
$ echo $HELLO
world
Environment variables are used for scripts all over your system. You can do things like set your favourite editor, e.g.:
export EDITOR="nano"
One useful thing you can do is set your prompt string, e.g.:
Bill:~$ export PS1="\u is awesome$ "
Bill is awesome$ ls
Bill is awesome$ du -h
Bill is awesome$ ...etc...
Each process that is created gets its own environment which lives as long as the process. Your shell is just like any other process. Its environment is its own.
If you type 'set' with no arguments, you'll see what exists. Many of these settings are there to control program behavior.. your search path, desired X11 display, home directory (if not /home/yourname), etc.
The use is really whatever you need it to be. Any time you need to store some useful bit of information (such as long list of command line options to some program) into a variable that other applications can read, or that you can access from the shell, use the environment.
For instance:
USUAL_CONFIGURE_OPTS="--prefix=/home/charlie --sysconfdir=/home/charlie/tmp-etc"
./configure $USUAL_CONFIGURE_OPTS --and-additional-arguments
Edit:
As a programmer, I read the environment to determine the user's preferences and obey them. For instance, the variable POSIXLY_CORRECT influences the output of my programs if it is set. The environment is where the user tells programs how to behave. It also happens, the environment is a handy place for the user to store useful bits, as I described above.
Again (responding to your comment), every program that is executed is a process. A process gets its own address space (own memory), its environment is stored in that space. This means, the environment is specific to that process and lives only as long as the process itself.
Edit 2:
I think that I now fully understand your question. If someone says 'virtual environment', they are just noting that the environment resides in the application's address space, which is mapped by the kernel as virtual memory (some pages might be in physical memory, some might be in swap, shared dynamic objects, etc).
No process can access another's environment unless the process explicitly creates a map to that specific region and shares it with another process. Again, a process' address space is completely private and isolated from other processes. Environmental variables live within that address space, otherwise, the process could not access or manipulate them.
Just as with the argument list, there is a section of memory allocated for the process that stores environment variables. I believe it is a \0 separated, unsorted list of KEY=VALUE pairs.
This bit of memory is copied with every fork() and not erased by exec() so any changes are copied into child processes.
The Unix shells do not write variables into this environment variable memory until export is used. That is the difference between shell variables and environment variables.
In the bash shell, "x=2" does not set an environment variable. "export x=2" or "x=2; export x" does.
Consider I have a program that needs an environment set. It is in Perl and I want to modify the environment (to search for libraries a special spot).
Every time I mess with the the standard way to do things in UNIX I pay a heavy price and I pay a penalty in flexibility.
I know that by using a simple shell script I will inject an additional process into the process tree. Any process accessing its own process tree might be thrown for a little bit of a loop.
Anything recursive to a nontrivial way would need to defend against multiple expansions of the environment.
Anything resembling being in a pipe of programs (or closing and opening STDIN, STDOUT, or STDERR) is my biggest area of concern.
What am I doing to myself?
What am I doing to myself?
Getting yourself all het up over nothing?
Wrapping a program in a shell script in order to set up the environment is actually quite standard and the risk is pretty minimal unless you're trying to do something really weird.
If you're really concerned about having one more process around — and UNIX processes are very cheap, by design — then use the exec keyword, which instead of forking a new process, simply exec's a new executable in place of the current one. So, where you might have had
#!/bin/bash -
FOO=hello
PATH=/my/special/path:${PATH}
perl myprog.pl
You'd just say
#!/bin/bash -
FOO=hello
PATH=/my/special/path:${PATH}
exec perl myprog.pl
and the spare process goes away.
This trick, however, is almost never worth the bother; the one counter-example is that if you can't change your default shell, it's useful to say
$ exec zsh
in place of just running the shell, because then you get the expected behavior for process control and so forth.