change environment variable on a running process in mac - macos

I have a running process on mac and I want to change is environment variable from out side the process, using some command line utility.
How can I do that?

You cannot change the environment variables of a running process via an external utility. Doing so would require the utility to modify the address space of the process. Note that this is not a limitation of macOS. This is a limitation of the UNIX process model. When a UNIX process is created by the kernel the environment variables are put in its address space; typically near the top of the stack. They are not stored in the kernel data structures for the process. And thus there are no system calls for getting or setting those vars. Which means there is no way for one process to affect the env vars of a second process other than at the time the second process is created via execve() or a related syscall.

Related

How to make PowerShell recognize changes in environment variables?

When I change any environment variable in Windows using GUI (System Properties/Environment Variables/System Variables) changes are reflected immediately in cmd terminal, but PowerShell shows an old value.
Here cmd recognized that I changed JAVA_HOME value from C:\Users\nikif\.jdks\openjdk-19.0.1 to C:\Users\nikif\.jdks\corretto-16.0.2
PowerShell still shows the previous value - C:\Users\nikif\.jdks\openjdk-19.0.1
Is there any command that will make PowerShell recognize the environment variable change made in GUI?
Or maybe there is a better way to change the environment variable from PowerShell?
Thank you.
This all should really be a comment (I tried above), but attempting to explain why the question, as it stands, is too vage requires just more explaination.
Processes get their environment when started by the OS. They basically get a copy the environment as it was at that point in time. When you start a process you can (using the respective APIs) pass additional or altered environment variables.
During the existance (runtime) of a process you cannot change the environment.
Shells are a common exception, as they provide specific syntax that does that (set NAME=VALUE in CMD.EXE and $env:NAME="VALUE" in PowerShell, for example). An application itself could also do such stuff from its code using respective APIs. But in general, there is no way to change variables from the outside.
One process will never see the changes done to the environment in a different process. For example, if you have to separate CMD.EXE sessions running and change a variable in one of them, the other will not know. The environment is private to each process.
A potential exception is the (global/system) environment variables you can set using the Computer/Properties/Environment setting (applet). The system will send a WM_SETTINGCHANGE window message indicating the that environment has changed. Applications can register to this message and act accordingly.
However, neither PowerShell nor CMD.EXE do seem to listen to this message (it would require a (hidden) Window anyway and both are console applications). And frankly, it would be not good if they did. Consider CMD.EXE just execuing a batch file and a variable (say PATH) changes underneath - security issues and general havoc all over.

adding new command to linux kernel

I have searched the web for long time without success. How can I add a new command to the kernel command line? e.g. a command like ver without any arguments, that simply prints Hello World message when executed.
The Linux kernel does not handle any commands (but the GRUB bootloader can pass some arguments to the booted kernel). It is just handling system calls. You could add some new one, but learn about advanced linux programming & syscalls(2) before hacking the kernel.
Perhaps you want to add a new command available to your shell. This is quite simple, put a new executable file (either an ELF executable, e.g. compiled from C code, or some script) in a directory known to your PATH. You might also make a new shell function.
The system call to create a new process is fork(2) (sometimes emulated thru some appropriate call to clone(2)...). fork is difficult to understand, so take several hours to read about it. Almost every process (with a few exceptions, notably /sbin/init) is created by fork. The system call to execute a new program is execve(2). Your shell will often use fork & execve to run commands (except builtin ones, like cd). Use strace(1) to understand what syscalls are done (by some program).
PS. Don't dare hacking your kernel before understanding quite well user-land Linux system programming....

Ruby: Setting environment variables using system()

I am creating the following method which sets my environment variables:
def set_time
puts "setting_time"
system("export GIT_COMMITTER_DATE='#{#date}'")
system("export GIT_AUTHOR_DATE='#{#date}'")
end
But for some reason when I go into my console after running this, the environment variables have not been added! I am able to run other command line interface keywords and it works. How can I set environment variables from Ruby?
The reason they don't 'stick' is because when you run a shell command from Ruby it opens a new process. And that process, as a child to your current Ruby process is not persistent, as eventually it dies.
A good resource on this is Jesse Storimer's blog post, with much more information about environment and processes than I will type here.
Depending on your operating system, you can use Ruby to write to your 'rc' files, such as ~/.bashrc or on Windows change your registry, if you really want to have these be persistent over logins.
So the answer is, you ARE setting and exporting environment variables. They simply aren't surviving past the life of the child process.

Whether Shellexecute will share environment variable with launching process

Program 1 uses SetEnvironment and calls ShellExecute to launch Program 2. Program 2 calls GetEnvironment and retrieves value from it. Surprisingly this is working as i have read in MSDN, SetEnvironment is process specific (at least in my case). Whether ShellExecute internally calls CreateProcess (as child process) which in turn allows Program 2 access ENV variable created and set in Program 1....I use SetEnvironment to create and use a altogether different ENV var than windows user and system vars.
It will share the environment, but not when running elevated (verb="runas").
Then you need to create an intermediate wrapper app (that is elevated) that set environment before re-launching using CreateProcess() or similar.
This is because a non-priviliged user may change the PATH to point to something bad (dir with malicious DLLs) and the elevated app would then be at risk, so one must work around this explicitly.

OS X: Attach to a running process and read its environment variables

Is it possible (and if so, how?) to read a running process's environment variables. To be more specific, I am concerned with environment variables set by the process itself (using setenv() or similar), not the general user session environment variables set when the process is launched.
I figured that DTrace would be the tool for this job, but the only solution I've found online (from this mailing list thread) appears to be specific to Solaris because the script fails to execute on my Mac.
Perhaps Instruments exposes this functionality somehow and I just haven't found it yet?
I have also tried Tasks Explorer, which is a nice little application, and it shows process info including environment variables, but it does not show any environment variables set by the process itself, which is what I'm after.
Any help would be much appreciated!
I suppose you could try next way:
Inject you dylib into running process.
To read environment variables from injected dylib.
Via IPC (RPC, Shared Memory, etc.) send Environment variable into you application.
By the way, I have a plan to add this type of environment variables exploring into my Tasks Explorer.
Next links will help you with injection:
https://github.com/comex/inject_and_interpose
SIMBL/Bundle/dylib injection into Dock.app

Resources