Programmatically Setting Terminal CWD

Discussion in 'Mac Programming' started by birchy, Aug 6, 2010.

  1. birchy macrumors newbie


    Aug 6, 2010
    Hi there,

    I am trying to create a command line utility that allows me to change directories in a terminal efficiently. Basically I want to be able to programmatically set the current working directory in (using either c++ or objective-c++).

    The following code (together with provided output) shows an example of the problem I am experiencing:
    #include <iostream>
    #include <string>
    using namespace std;
    #define COLOR_RED   "\E[0;31;48m"
    #define COLOR_BLACK "\E[0;30;48m"
    #define PERROR() fprintf(stderr,"  %sERROR:%s ", COLOR_RED, COLOR_BLACK)
    #define D_ERROR( e, msg, ... ) do{ PERROR(); fprintf( stderr, msg , ## __VA_ARGS__); fprintf(stderr,"\n"); exit(e); } while(0)
    //#define _SOL1
    string getCWD() {
        char result[FILENAME_MAX];
        if( !getcwd( result, sizeof(result) ) )
            D_ERROR( -1, "Could not get current working directory.\n" );
        return string( result, (strlen(result) > 0) ? strlen(result) : 0 );
    int setCWD( const char *path ) {
    #ifdef _SOL1
        BOOL success;
        NSFileManager *fm = [NSFileManager defaultManager];
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSString *nsPath = [NSString stringWithCString:path encoding:[NSString defaultCStringEncoding]];
        success = [fm changeCurrentDirectoryPath: nsPath];
        [pool release];
        if( success == YES ) return 0;
        if( !chdir( path ) ) return 0;
        return -1;
    int main( int argc, char **argv ) {
        fprintf( stdout, "  Current Directory: %s\n", getCWD().c_str() );
        fprintf( stdout, "  Enter Desired CWD: " );
        string dir;
        getline( cin, dir );
        int e = setCWD( dir.c_str() );
        if( e == 0 ) {
            fprintf( stdout, "  Current Directory: %s\n", getCWD().c_str() );
            return 0;
        fprintf( stderr, "Could not change cwd to %s.\n", dir.c_str() );
        return -1;
    And this output:
    birchy-mac: pwd
    birchy-mac: ./cwd.out
      Current Directory: /Users/birchy/Dev/cwd
      Enter Desired CWD: /Users/
      Current Directory: /Users
    birchy-mac: pwd
    It appears that the current working directory is being changed successfully within the scope of the application, however the current working directory of does not change (as is apparent by the output of pwd after execution of the application).

    I have tried both of the shown implementations within setCWD, (ie traditional UNIX way and the Cocoa way) yet both exhibit this same behaviour.

    Does anyone have any idea why this is happening?
    Does anyone know how I can solve this issue?

    Help would be much appreciated.
    Thanks in advance!
  2. mrbash macrumors 6502

    Aug 10, 2008
    Unfortunately you cannot do what you are trying to do because executing a program is essentially forking, you won't be able to modify the parent process's environment from the child.
    What you can do instead is to wrap your program in a script that will change the current directory based on some input from your program.

    cd `/path/to/myprogram`
    note that I am not using the apostrophe, but the the other character below ~ on your keyboard.
  3. birchy thread starter macrumors newbie


    Aug 6, 2010
    Yes, I could wrap it in a bash script.

    Actually, the original implementation of this utility was done in bash, however I was having issues supporting the script on multiple platforms, so I decided to take a shot at implementing the utility in c++.

    This being said, it is my intension to implement this entirely in c++/objective-c++.

    Anyone know of a workaround to this issue?

    Is it possible to capture the pid of the parent ( and then set the id of another process (
  4. chown33 macrumors 604

    Aug 9, 2009
    So many bees
    There is no workaround. No process can directly change the working directory of another process. If it could, it would be an exploitable security hole.

    The best you can do is to somehow trigger the execution of code in the target process, which then changes its own working directory.
  5. lee1210 macrumors 68040


    Jan 10, 2005
    Dallas, TX
    I'd alias a command to "cd `dir_changalator`". Then when you run your alias, your program executes, and its output is passed to cd.

  6. asciimov macrumors newbie

    Jan 31, 2008

    First lets get everybody on the same page:

    1) you need this script, save it as cwd in /usr/local/bin

    printf "\tCurrent Directory: %s\n" $(pwd)
    printf "\tEnter Desired CWD: "
    read input_dir
    cd $input_dir
    printf "\tCurrent Directory: %s\n" $(pwd)
    2) set the permissions for the script, we need to be able to execute it, from the terminal type

    chmod 711 cwd
    3) the shell forks executables, the command "source" runs the executable without forking, from the terminal type

    source ./cwd

    . ./cwd
    4) #3 looks ugly you say, well then lets make an "alias"

    if /usr/local/bin is in your $PATH
    alias cwd="source cwd"
    -or- if /usr/local/bin is not in your $PATH

    alias cwd="source /usr/local/bin/cwd"
    Second, I don't like this program/script. 1) it doesn't have tab completions, which saves tons of key strokes 2) its an interactive script, which limits its usefulness 3) you can have your shell display the current directory before the prompt. 4) why do in C++ what you can do in a very simple script?

    Finally, I feel that this is probably somebodies homework but oh well. If you want a new exercise, figure out how to do this in an alias, not that I condone such use...

Share This Page