/// Silly function.
static void builtin_complete_add2(const wchar_t *cmd, int cmd_type, const wchar_t *short_opt,
                                  const wcstring_list_t &gnu_opt, const wcstring_list_t &old_opt,
                                  int result_mode, const wchar_t *condition, const wchar_t *comp,
                                  const wchar_t *desc, int flags) {
    size_t i;
    const wchar_t *s;

    for (s = short_opt; *s; s++) {
        complete_add(cmd, cmd_type, wcstring(1, *s), option_type_short, result_mode, condition,
                     comp, desc, flags);
    }

    for (i = 0; i < gnu_opt.size(); i++) {
        complete_add(cmd, cmd_type, gnu_opt.at(i), option_type_double_long, result_mode, condition,
                     comp, desc, flags);
    }

    for (i = 0; i < old_opt.size(); i++) {
        complete_add(cmd, cmd_type, old_opt.at(i), option_type_single_long, result_mode, condition,
                     comp, desc, flags);
    }

    if (old_opt.empty() && gnu_opt.empty() && wcslen(short_opt) == 0) {
        complete_add(cmd, cmd_type, wcstring(), option_type_args_only, result_mode, condition, comp,
                     desc, flags);
    }
}
/**
   Silly function
*/
static void  builtin_complete_remove2(const wchar_t *cmd,
                                      int cmd_type,
                                      const wchar_t *short_opt,
                                      const wcstring_list_t &gnu_opt,
                                      const wcstring_list_t &old_opt)
{
    const wchar_t *s = (wchar_t *)short_opt;
    if (*s)
    {
        for (; *s; s++)
        {
            if (old_opt.empty() && gnu_opt.empty())
            {
                complete_remove(cmd,
                                cmd_type,
                                *s,
                                0,
                                0);

            }
            else
            {
                builtin_complete_remove3(cmd,
                                         cmd_type,
                                         *s,
                                         gnu_opt,
                                         0);
                builtin_complete_remove3(cmd,
                                         cmd_type,
                                         *s,
                                         old_opt,
                                         1);
            }
        }
    }
    else if (gnu_opt.empty() && old_opt.empty())
    {
        complete_remove(cmd,
                        cmd_type,
                        0,
                        0,
                        0);
    }
    else
    {
        builtin_complete_remove3(cmd,
                                 cmd_type,
                                 0,
                                 gnu_opt,
                                 0);
        builtin_complete_remove3(cmd,
                                 cmd_type,
                                 0,
                                 old_opt,
                                 1);

    }


}
Exemple #3
0
void function_prepare_environment(const wcstring &name, const wchar_t *const *argv,
                                  const std::map<wcstring, env_var_t> &inherited_vars) {
    // Three components of the environment:
    // 1. argv
    // 2. named arguments
    // 3. inherited variables
    env_set_argv(argv);

    const wcstring_list_t named_arguments = function_get_named_arguments(name);
    if (!named_arguments.empty()) {
        const wchar_t *const *arg;
        size_t i;
        for (i = 0, arg = argv; i < named_arguments.size(); i++) {
            env_set(named_arguments.at(i).c_str(), *arg, ENV_LOCAL | ENV_USER);

            if (*arg) arg++;
        }
    }

    for (std::map<wcstring, env_var_t>::const_iterator it = inherited_vars.begin(),
                                                       end = inherited_vars.end();
         it != end; ++it) {
        env_set(it->first, it->second.missing() ? NULL : it->second.c_str(), ENV_LOCAL | ENV_USER);
    }
}
Exemple #4
0
// Validate the given path `list`. If there are any entries referring to invalid directories which
// contain a colon, then complain. Return true if any path element was valid, false if not.
static bool validate_path_warning_on_colons(const wchar_t *cmd,
                                            const wchar_t *key,  //!OCLINT(npath complexity)
                                            const wcstring_list_t &list, io_streams_t &streams,
                                            const environment_t &vars) {
    // Always allow setting an empty value.
    if (list.empty()) return true;

    bool any_success = false;

    // Don't bother validating (or complaining about) values that are already present. When
    // determining already-present values, use ENV_DEFAULT instead of the passed-in scope because
    // in:
    //
    //   set -l PATH stuff $PATH
    //
    // where we are temporarily shadowing a variable, we want to compare against the shadowed value,
    // not the (missing) local value. Also don't bother to complain about relative paths, which
    // don't start with /.
    wcstring_list_t existing_values;
    const auto existing_variable = vars.get(key, ENV_DEFAULT);
    if (!existing_variable.missing_or_empty()) existing_variable->to_list(existing_values);

    for (const wcstring &dir : list) {
        if (!string_prefixes_string(L"/", dir) || contains(existing_values, dir)) {
            any_success = true;
            continue;
        }

        const wchar_t *colon = std::wcschr(dir.c_str(), L':');
        bool looks_like_colon_sep = colon && colon[1];
        if (!looks_like_colon_sep && any_success) {
            // Once we have one valid entry, skip the remaining ones unless we might warn.
            continue;
        }
        struct stat buff;
        bool valid = true;
        if (wstat(dir, &buff) == -1) {
            valid = false;
        } else if (!S_ISDIR(buff.st_mode)) {
            errno = ENOTDIR;
            valid = false;
        } else if (waccess(dir, X_OK) == -1) {
            valid = false;
        }
        if (valid) {
            any_success = true;
        } else if (looks_like_colon_sep) {
            streams.err.append_format(BUILTIN_SET_PATH_ERROR, cmd, key, dir.c_str(),
                                      std::strerror(errno));
            streams.err.append_format(BUILTIN_SET_PATH_HINT, cmd, key, key,
                                      std::wcschr(dir.c_str(), L':') + 1);
        }
    }
    return any_success;
}
Exemple #5
0
void parse_util_set_argv(const wchar_t * const *argv, const wcstring_list_t &named_arguments)
{
    if (*argv)
    {
        const wchar_t * const *arg;
        wcstring sb;

        for (arg=argv; *arg; arg++)
        {
            if (arg != argv)
            {
                sb.append(ARRAY_SEP_STR);
            }
            sb.append(*arg);
        }

        env_set(L"argv", sb.c_str(), ENV_LOCAL);
    }
    else
    {
        env_set(L"argv", 0, ENV_LOCAL);
    }

    if (! named_arguments.empty())
    {
        const wchar_t * const *arg;
        size_t i;
        for (i=0, arg=argv; i < named_arguments.size(); i++)
        {
            env_set(named_arguments.at(i).c_str(), *arg, ENV_LOCAL | ENV_USER);

            if (*arg)
                arg++;
        }
    }
}
/**
   Silly function
*/
static void  builtin_complete_add2(const wchar_t *cmd,
                                   int cmd_type,
                                   const wchar_t *short_opt,
                                   const wcstring_list_t &gnu_opt,
                                   const wcstring_list_t &old_opt,
                                   int result_mode,
                                   const wchar_t *condition,
                                   const wchar_t *comp,
                                   const wchar_t *desc,
                                   int flags)
{
    size_t i;
    const wchar_t *s;

    for (s=short_opt; *s; s++)
    {
        complete_add(cmd,
                     cmd_type,
                     *s,
                     0,
                     0,
                     result_mode,
                     condition,
                     comp,
                     desc,
                     flags);
    }

    for (i=0; i<gnu_opt.size(); i++)
    {
        complete_add(cmd,
                     cmd_type,
                     0,
                     gnu_opt.at(i).c_str(),
                     0,
                     result_mode,
                     condition,
                     comp,
                     desc,
                     flags);
    }

    for (i=0; i<old_opt.size(); i++)
    {
        complete_add(cmd,
                     cmd_type,
                     0,
                     old_opt.at(i).c_str(),
                     1,
                     result_mode,
                     condition,
                     comp,
                     desc,
                     flags);
    }

    if (old_opt.empty() && gnu_opt.empty() && wcslen(short_opt) == 0)
    {
        complete_add(cmd,
                     cmd_type,
                     0,
                     0,
                     0,
                     result_mode,
                     condition,
                     comp,
                     desc,
                     flags);
    }
}
Exemple #7
0
/**
   Call env_set. If this is a path variable, e.g. PATH, validate the
   elements. On error, print a description of the problem to stderr.
*/
static int my_env_set(const wchar_t *key, const wcstring_list_t &val, int scope)
{
    size_t i;
    int retcode = 0;
    const wchar_t *val_str=NULL;

    if (is_path_variable(key))
    {
        /* Fix for https://github.com/fish-shell/fish-shell/issues/199 . Return success if any path setting succeeds. */
        bool any_success = false;

        /* Don't bother validating (or complaining about) values that are already present */
        wcstring_list_t existing_values;
        const env_var_t existing_variable = env_get_string(key, scope);
        if (! existing_variable.missing_or_empty())
            tokenize_variable_array(existing_variable, existing_values);

        for (i=0; i< val.size() ; i++)
        {
            const wcstring &dir = val.at(i);
            if (list_contains_string(existing_values, dir))
            {
                any_success = true;
                continue;
            }

            bool show_perror = false;
            int show_hint = 0;
            bool error = false;

            struct stat buff;
            if (wstat(dir, &buff))
            {
                error = true;
                show_perror = true;
            }

            if (!(S_ISDIR(buff.st_mode)))
            {
                error = true;
            }

            if (!error)
            {
                any_success = true;
            }
            else
            {
                append_format(stderr_buffer, _(BUILTIN_SET_PATH_ERROR), L"set", dir.c_str(), key);
                const wchar_t *colon = wcschr(dir.c_str(), L':');

                if (colon && *(colon+1))
                {
                    show_hint = 1;
                }

            }

            if (show_perror)
            {
                builtin_wperror(L"set");
            }

            if (show_hint)
            {
                append_format(stderr_buffer, _(BUILTIN_SET_PATH_HINT), L"set", key, key, wcschr(dir.c_str(), L':')+1);
            }

        }

        /* Fail at setting the path if we tried to set it to something non-empty, but it wound up empty. */
        if (! val.empty() && ! any_success)
        {
            return 1;
        }

    }

    wcstring sb;
    if (! val.empty())
    {
        for (i=0; i< val.size() ; i++)
        {
            sb.append(val[i]);
            if (i<val.size() - 1)
            {
                sb.append(ARRAY_SEP_STR);
            }
        }
        val_str = sb.c_str();
    }

    switch (env_set(key, val_str, scope | ENV_USER))
    {
        case ENV_PERM:
        {
            append_format(stderr_buffer, _(L"%ls: Tried to change the read-only variable '%ls'\n"), L"set", key);
            retcode=1;
            break;
        }

        case ENV_SCOPE:
        {
            append_format(stderr_buffer, _(L"%ls: Tried to set the special variable '%ls' with the wrong scope\n"), L"set", key);
            retcode=1;
            break;
        }

        case ENV_INVALID:
        {
            append_format(stderr_buffer, _(L"%ls: Tried to set the special variable '%ls' to an invalid value\n"), L"set", key);
            retcode=1;
            break;
        }
    }

    return retcode;
}
/**
   Call env_set. If this is a path variable, e.g. PATH, validate the
   elements. On error, print a description of the problem to stderr.
*/
static int my_env_set(const wchar_t *key, const wcstring_list_t &val, int scope, io_streams_t &streams)
{
    size_t i;
    int retcode = 0;
    const wchar_t *val_str=NULL;

    if (is_path_variable(key))
    {
        /* Fix for https://github.com/fish-shell/fish-shell/issues/199 . Return success if any path setting succeeds. */
        bool any_success = false;

        /* Don't bother validating (or complaining about) values that are already present.
           When determining already-present values, use ENV_DEFAULT instead of the passed-in scope because in:
              set -l PATH stuff $PATH
           where we are temporarily shadowing a variable, we want to compare against the shadowed value, not the
           (missing) local value.
           Also don't bother to complain about relative paths, which don't start with /.
        */
        wcstring_list_t existing_values;
        const env_var_t existing_variable = env_get_string(key, ENV_DEFAULT);
        if (! existing_variable.missing_or_empty())
            tokenize_variable_array(existing_variable, existing_values);

        for (i=0; i< val.size() ; i++)
        {
            const wcstring &dir = val.at(i);
            if (!string_prefixes_string(L"/", dir) || list_contains_string(existing_values, dir))
            {
                any_success = true;
                continue;
            }

            bool show_perror = false;
            int show_hint = 0;
            bool error = false;

            struct stat buff;
            if (wstat(dir, &buff))
            {
                error = true;
                show_perror = true;
            }

            if (!(S_ISDIR(buff.st_mode)))
            {
                error = true;
            }

            if (!error)
            {
                any_success = true;
            }
            else
            {
                streams.err.append_format(_(BUILTIN_SET_PATH_ERROR), L"set", dir.c_str(), key);
                const wchar_t *colon = wcschr(dir.c_str(), L':');

                if (colon && *(colon+1))
                {
                    show_hint = 1;
                }

            }

            if (show_perror)
            {
                builtin_wperror(L"set", streams);
            }

            if (show_hint)
            {
                streams.err.append_format(_(BUILTIN_SET_PATH_HINT), L"set", key, key, wcschr(dir.c_str(), L':')+1);
            }

        }

        /* Fail at setting the path if we tried to set it to something non-empty, but it wound up empty. */
        if (! val.empty() && ! any_success)
        {
            return 1;
        }

    }

    wcstring sb;
    if (! val.empty())
    {
        for (i=0; i< val.size() ; i++)
        {
            sb.append(val[i]);
            if (i<val.size() - 1)
            {
                sb.append(ARRAY_SEP_STR);
            }
        }
        val_str = sb.c_str();
    }

    switch (env_set(key, val_str, scope | ENV_USER))
    {
        case ENV_PERM:
        {
            streams.err.append_format(_(L"%ls: Tried to change the read-only variable '%ls'\n"), L"set", key);
            retcode=1;
            break;
        }

        case ENV_SCOPE:
        {
            streams.err.append_format(_(L"%ls: Tried to set the special variable '%ls' with the wrong scope\n"), L"set", key);
            retcode=1;
            break;
        }

        case ENV_INVALID:
        {
            streams.err.append_format(_(L"%ls: Tried to set the special variable '%ls' to an invalid value\n"), L"set", key);
            retcode=1;
            break;
        }
    }

    return retcode;
}
Exemple #9
0
/**
   Call env_set. If this is a path variable, e.g. PATH, validate the
   elements. On error, print a description of the problem to stderr.
*/
static int my_env_set( const wchar_t *key, const wcstring_list_t &val, int scope )
{
    size_t i;
    int retcode = 0;
    const wchar_t *val_str=NULL;
    
    if( is_path_variable( key ) )
    {
        /* Fix for https://github.com/fish-shell/fish-shell/issues/199 . Return success if any path setting succeeds. */
        bool any_success = false, any_error = false;
        
        for( i=0; i< val.size() ; i++ )
        {
            bool show_perror = false;
            int show_hint = 0;
            bool error = false;
            
            struct stat buff;
            const wchar_t *dir = val[i].c_str();
            
            if( wstat( dir, &buff ) )
            {
                error = true;
                show_perror = true;
            }
            
            if( !( S_ISDIR(buff.st_mode) ) )
            {
                error = true;
            }
            
            if( !error )
            {
                any_success = true;
            }
            else
            {
                any_error = true;
                const wchar_t *colon;
                append_format(stderr_buffer, _(BUILTIN_SET_PATH_ERROR), L"set", dir, key);
                colon = wcschr( dir, L':' );
                
                if( colon && *(colon+1) ) 
                {
                    show_hint = 1;
                }
                
            }
            
            if( show_perror )
            {
                builtin_wperror( L"set" );
            }
            
            if( show_hint )
            {
                append_format(stderr_buffer, _(BUILTIN_SET_PATH_HINT), L"set", key, key, wcschr( dir, L':' )+1);
            }
            
        }
        
        /* Fail at setting the path if we tried to set it to something non-empty, but it wound up empty. */
        if( ! val.empty() && ! any_success )
        {
            return 1;
        }
        
    }
    
    wcstring sb;
    if(  val.size() )
    {
        for( i=0; i< val.size() ; i++ )
        {
            sb.append(val[i]);
            if( i<val.size() - 1 )
            {
                sb.append( ARRAY_SEP_STR );
            }
        }
        val_str = sb.c_str();
    }
    
    switch( env_set( key, val_str, scope | ENV_USER ) )
    {
        case ENV_PERM:
        {
            append_format(stderr_buffer, _(L"%ls: Tried to change the read-only variable '%ls'\n"), L"set", key);
            retcode=1;
            break;
        }
            
        case ENV_INVALID:
        {
            append_format(stderr_buffer, _(L"%ls: Unknown error"), L"set" );
            retcode=1;
            break;
        }
    }
    
    return retcode;
}