diff options
author | 2011-12-26 19:18:46 -0800 | |
---|---|---|
committer | 2011-12-26 19:18:46 -0800 | |
commit | 8d2f107d61a8b0e099ab9a59b8a32c236da5a5fc (patch) | |
tree | 89f718ab74f8400332534aee237c6f925348f05c /path.cpp | |
parent | 3f16ace6784caab54fb054836ee93902e9701913 (diff) |
Some changes to migrate towards C++ and a multithreaded model
Diffstat (limited to 'path.cpp')
-rw-r--r-- | path.cpp | 218 |
1 files changed, 197 insertions, 21 deletions
@@ -25,14 +25,115 @@ */ #define MISSING_COMMAND_ERR_MSG _( L"Error while searching for command '%ls'" ) +bool path_get_path_string(const wcstring &cmd_str, wcstring &output, const env_vars &vars) +{ + const wchar_t * const cmd = cmd_str.c_str(); + int err = ENOENT; + debug( 3, L"path_get_path_string( '%ls' )", cmd ); + + if(wcschr( cmd, L'/' ) != 0 ) + { + if( waccess( cmd, X_OK )==0 ) + { + struct stat buff; + if(wstat( cmd, &buff )) + { + return false; + } + + if (S_ISREG(buff.st_mode)) + { + output = cmd_str; + return true; + } + else + { + errno = EACCES; + return false; + } + } + else + { + //struct stat buff; + //wstat( cmd, &buff ); + return false; + } + + } + else + { + const wchar_t *path = vars.get(L"PATH"); + if( path == 0 ) + { + if( contains( PREFIX L"/bin", L"/bin", L"/usr/bin" ) ) + { + path = L"/bin" ARRAY_SEP_STR L"/usr/bin"; + } + else + { + path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin"; + } + } + + wcstokenizer tokenizer(path, ARRAY_SEP_STR); + wcstring new_cmd; + while (tokenizer.next(new_cmd)) + { + size_t path_len = new_cmd.size(); + if (path_len == 0) continue; + + append_path_component(new_cmd, cmd_str); + if( waccess( new_cmd.c_str(), X_OK )==0 ) + { + struct stat buff; + if( wstat( new_cmd.c_str(), &buff )==-1 ) + { + if( errno != EACCES ) + { + wperror( L"stat" ); + } + continue; + } + if( S_ISREG(buff.st_mode) ) + { + output = new_cmd; + return true; + } + err = EACCES; + + } + else + { + switch( errno ) + { + case ENOENT: + case ENAMETOOLONG: + case EACCES: + case ENOTDIR: + break; + default: + { + debug( 1, + MISSING_COMMAND_ERR_MSG, + new_cmd.c_str() ); + wperror( L"access" ); + } + } + } + } + } + + errno = err; + return false; +} wchar_t *path_get_path( void *context, const wchar_t *cmd ) { wchar_t *path; int err = ENOENT; - + CHECK( cmd, 0 ); debug( 3, L"path_get_path( '%ls' )", cmd ); @@ -46,7 +147,7 @@ wchar_t *path_get_path( void *context, const wchar_t *cmd ) { return 0; } - + if( S_ISREG(buff.st_mode) ) return halloc_wcsdup( context, cmd ); else @@ -61,7 +162,7 @@ wchar_t *path_get_path( void *context, const wchar_t *cmd ) wstat( cmd, &buff ); return 0; } - + } else { @@ -77,12 +178,12 @@ wchar_t *path_get_path( void *context, const wchar_t *cmd ) path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin"; } } - + /* Allocate string long enough to hold the whole command */ - wchar_t *new_cmd = halloc( context, sizeof(wchar_t)*(wcslen(cmd)+wcslen(path)+2) ); - + wchar_t *new_cmd = (wchar_t *)halloc( context, sizeof(wchar_t)*(wcslen(cmd)+wcslen(path)+2) ); + /* We tokenize a copy of the path, since strtok modifies its arguments @@ -90,7 +191,7 @@ wchar_t *path_get_path( void *context, const wchar_t *cmd ) wchar_t *path_cpy = wcsdup( path ); wchar_t *nxt_path = path; wchar_t *state; - + if( (new_cmd==0) || (path_cpy==0) ) { DIE_MEM(); @@ -124,7 +225,7 @@ wchar_t *path_get_path( void *context, const wchar_t *cmd ) return new_cmd; } err = EACCES; - + } else { @@ -154,7 +255,82 @@ wchar_t *path_get_path( void *context, const wchar_t *cmd ) } -wchar_t *path_get_cdpath( void *context, wchar_t *dir ) +bool path_get_cdpath_string(const wcstring &dir_str, wcstring &result, const env_vars &vars) +{ + wchar_t *res = 0; + int err = ENOENT; + bool success = false; + + const wchar_t *const dir = dir_str.c_str(); + if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) ) + { + struct stat buf; + if( wstat( dir, &buf ) == 0 ) + { + if( S_ISDIR(buf.st_mode) ) + { + result = dir_str; + success = true; + } + else + { + err = ENOTDIR; + } + + } + } + else + { + const wchar_t *path = vars.get(L"CDPATH"); + if( !path || !wcslen(path) ) + { + path = L"."; + } + + wcstokenizer tokenizer(path, ARRAY_SEP_STR); + wcstring next_path; + while (tokenizer.next(next_path)) + { + expand_tilde(next_path); + if (next_path.size() == 0) continue; + + wcstring whole_path = next_path; + append_path_component(whole_path, dir); + + struct stat buf; + if( wstat( whole_path.c_str(), &buf ) == 0 ) + { + if( S_ISDIR(buf.st_mode) ) + { + result = whole_path; + success = true; + break; + } + else + { + err = ENOTDIR; + } + } + else + { + if( lwstat( whole_path.c_str(), &buf ) == 0 ) + { + err = EROTTEN; + } + } + } + } + + + if( !success ) + { + errno = err; + } + + return res; +} + +wchar_t *path_get_cdpath( void *context, const wchar_t *dir ) { wchar_t *res = 0; int err = ENOENT; @@ -205,7 +381,7 @@ wchar_t *path_get_cdpath( void *context, wchar_t *dir ) nxt_path != 0; nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) ) { - wchar_t *expanded_path = expand_tilde( wcsdup(nxt_path) ); + wchar_t *expanded_path = expand_tilde_compat( wcsdup(nxt_path) ); // debug( 2, L"woot %ls\n", expanded_path ); @@ -229,7 +405,7 @@ wchar_t *path_get_cdpath( void *context, wchar_t *dir ) if( S_ISDIR(buf.st_mode) ) { res = whole_path; - halloc_register( context, whole_path ); + halloc_register( context, whole_path ); break; } else @@ -244,7 +420,7 @@ wchar_t *path_get_cdpath( void *context, wchar_t *dir ) err = EROTTEN; } } - + free( whole_path ); } free( path_cpy ); @@ -264,7 +440,7 @@ wchar_t *path_get_config( void *context) wchar_t *xdg_dir, *home; int done = 0; wchar_t *res = 0; - + xdg_dir = env_get( L"XDG_CONFIG_HOME" ); if( xdg_dir ) { @@ -277,10 +453,10 @@ wchar_t *path_get_config( void *context) { free( res ); } - + } else - { + { home = env_get( L"HOME" ); if( home ) { @@ -295,7 +471,7 @@ wchar_t *path_get_config( void *context) } } } - + if( done ) { halloc_register_function( context, &free, res ); @@ -306,16 +482,16 @@ wchar_t *path_get_config( void *context) debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." )); return 0; } - + } wchar_t *path_make_canonical( void *context, const wchar_t *path ) { wchar_t *res = halloc_wcsdup( context, path ); wchar_t *in, *out; - + in = out = res; - + while( *in ) { if( *in == L'/' ) @@ -326,7 +502,7 @@ wchar_t *path_make_canonical( void *context, const wchar_t *path ) } } *out = *in; - + out++; in++; } @@ -340,7 +516,7 @@ wchar_t *path_make_canonical( void *context, const wchar_t *path ) out--; } *out = 0; - + return res; } |