How to Set the Working Directory of the Parent Process

How do I set the working directory of the parent process?

Don't do this.

FILE *p;
char cmd[32];
p = fopen("/tmp/gdb_cmds", "w");
fprintf(p, "call chdir(\"..\")\ndetach\nquit\n");
fclose(p);
sprintf(cmd, "gdb -p %d -batch -x /tmp/gdb_cmds", getppid());
system(cmd);

It will probably work, though note that Bash's pwd command is cached and won't notice.

Change current working directory in child process in C

You have two mistakes,

  • Usage of scanf()
  • Not waiting for child to finish its task as parent.

The following works.

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>

int main()
{
int pid;
char directory[1024];
char newdirectory[1024];
pid=fork();
if(pid<0)
{
printf("\n Error ");
exit(1);
}
else if(pid==0)
{
printf("I'm child \n ");
printf(" My PID: %d \n",getpid());
getcwd(directory, sizeof(directory));
printf(" My current working directory is: %s\n", directory);
printf(" Enter the new path\n");
scanf("%1023s", newdirectory);
chdir(newdirectory);
getcwd(directory, sizeof(directory));
printf(" Path changed to: %s\n", directory);
exit(0);
}
else
{
wait(0);
printf("I'm a parent \n ");
printf("My PID is %d \n ",getpid());
printf("Bye bye \n");
exit(1);
}
}

How to change the parent working directory from which my executable is run?

In general, you can't do this. No program can change its parent process's directory, no matter what language it's written in, using standard UNIX interfaces. A program can only change its own directory (and, by extension, the initial working directory of any programs it subsequently starts).

However, with the shell's active participation, you can make something very similar. Consider instructing your users to run a shell function such as the following:

# this wrapper works on any POSIX shell, but will avoid setting a global variable "dir" if
# the active shell (like bash, ksh, or even dash) supports local variables.
chdirWithMyHaskellProgram() {
local dir 2>/dev/null || \
declare dir 2>/dev/null || \
: "current shell does not support local variables; proceeding anyhow"
dir="$(myHaskellProgram "$@")" && cd -- "$dir"
}

...will cause chdirWithMyHaskellProgram --foo-bar to call myHaskelProgram --foo-bar, and change to the directory named in the output of same, if and only if the exit status indicates success.


Consider having myHaskelProgram --eval emit the source code to the above function. If you implemented this, then your user would need to put eval "$(myHaskelProgram --eval)" in their dotfiles, but would thereafter have the desired functionality.

Changing the current working directory of cmd (from a child process)

I got it working. As was suggested SendInput finally did the trick.
I used a combination of WinAPI calls to GetForegroundWindow() / SetForegroundWindow() and the Windows Forms System.Windows.Forms.SendKeys.SendWait() Method to achieve what I wanted:

Upon calling my cd-wrapper program (sd.exe) and providing my custom target directory (~/ home) it generates the corresponding command along with the "Enter-Pressed-Event" to be sent to it's parent cmd process.

Sample Image

Here's the complete C# code:

if (args.Length != 1)
{
Console.WriteLine(Directory.GetCurrentDirectory());
return;
}
string targetDirectory = args[0];
string command = string.Empty;
if (targetDirectory.Equals("~"))
{
command = @"pushd C:\Users\fred\Desktop";
}
else if (!Directory.Exists(targetDirectory))
{
Console.WriteLine("I/O Error: No such file or directory.");
return;
}
else
{
command = @"cd " + targetDirectory;
}
Target target = Target.Create(Process.GetCurrentProcess().GetParentProcess());
target.SendKeys(command + "{ENTER}", true);

Note that I kind of started to write a complete Framework for this and similar problems alongside this project that contains all my different approaches to this question and the low level WinAPI calls as well as the Extension methods to get the parent process :D

As it would be a bit overkill to paste all of it's code in this answer, here's the GitHub. If I can find the time I'll go ahead and optimize the code, but for now this'll do. Hope this helps anyone encountering a similar problem :)

Edit:

An even "cleaner" way is to use dll injection to directly make cmd switch it's working directory. While it is a lot harder to get working it has the advantage of not littering the cmd command history as compared to the approach described above. In addition to that cmd seems to be aware of any changes to it's current working directory, so it automatically updates the prompt text. Once I have a fully working example, that allows to dynamically specify the target directory I will post it here :)

Get working directory of the parent shell from a child process

Yes, just use $PWD or pwd.

If you call /location2/script2.sh from /location1/script1.sh, then the current working directory of script2.sh will always be /location1, not /location2.

How to change the shell's current working directory in Go?

You can't do this; every child process has its own working directory inherited from the parent. In this case, your cd gets its working directory from its parent (your shell). A child process can't change the directory – or any other state – of the parent process.

This is basic process separation. Allowing child processes to influence their parent would have all sorts of security and usability issues.

Shells implement cd as a "special builtin". It's not an external binary:

$ where cd
cd: shell built-in command

In other words, when the shell runs the cd command it's run in the same process as the rest of the shell.

The basic logic of a shell's REPL looks something like:

for {
line := waitForInputLine()
switch {
case strings.HasPrefix(line, "cd"):
os.chdir(strings.Split(line, " ")[1])

// ..check other builtins and special cases./

default:
runBinary(line)
}
}

There is no way you can implement that in an external binary, no matter which language you use to implement it.

Parent Process Directory not recognized by the Icon and Background Image fields in Windows Terminal

Found a solution in this article

In the Icon and Background fields, you can reference your files relative to your current working directory:

%__CD__%\relative_path_to_icon_file. In my case it would be %__CD__%\graphics\app_bckgnd.jpg.

Parent program's working directory is not searched for DLLs when child program is started with CreateProcess

Your original question asked why the child process does not inherit the working directory of the parent. Well, if you pass NULL to CreateProcess then the new process will inherit the working directory of the parent process at the time that the call to CreateProcess is made. The documentation makes this quite clear and there are no surprises here. CreateProcess behaves precisely as advertised.

The edited question concentrates on DLL search. It's not easy to answer this new take on the question from this information. The best thing to do is to run the program under the profile mode of Dependency Walker. This should reveal what is wrong. You may well find that the problem is not at all what you expect it to be.

And for future reference, I recommend that you include full details of any errors when you ask a question. You stated that an exception was raised but really you need to supply the full details of any exceptions.

Is it possible to maintain the python working directory that I changed before

Nope. That's an operating system thing: the Python subprocess is changing its working directory, but that can't affect its parent process (such as a Bash shell you're launching it from).

If the Python process is meant to change your directory - let's say you're writing your own improved cd program - you could do something like:

  • Have your program print the name of the directory to change to
  • Have your shell itself change to your program's output

For example, say you have a Python program like:

#!/usr/bin/env python

print('/tmp/pancakes')

You could run it from your shell this way:

$ pwd
/tmp
$ cd $(python mycd.py)
$ pwd
/tmp/pancakes

See? Now you've changed to the new directory! Alternatively, you could make a handy alias like:

$ pwd
/tmp
$ alias mycd='cd $(python mycd.py)'
$ mycd
$ pwd
/tmp/pancakes

so that you don't have to remember the syntax every single time. But really, without some dire platform-specific shenanigans (example: Changing a process's current working directory programmatically) but if you value your sanity, trust me, you really don't want to go down that road. You'd be much better off learning how to work within your OS's process model, even if it feels wonky, than to try to work around it.


Edit: you've added some clarifying answers since the post, which really changes what you were asking. That may be a little easier, but I still strongly suggest you not go down this path.

  • Consider that Python has a startup file.
  • Ponder that Python has exit handlers.
  • Wonder what would happen if an exit handler wrote your current working directory name out to a file.
  • Think of what would happen if the startup file read that file and changed to the directory named in it.
  • Realize that this is probably a Really Bad Idea because half the time you launch Python it'll be working in a different directory than you think it is. What happens if you run import foo? Who knows! Let's roll some dice and find out!


Related Topics



Leave a reply



Submit