示例#1
0
/// Set the new value of the specified resource limit. This function does _not_ multiply the limit
// value by the multiplier constant used by the commandline ulimit.
static int set(int resource, int hard, int soft, rlim_t value, io_streams_t &streams) {
    struct rlimit ls;
    getrlimit(resource, &ls);

    if (hard) {
        ls.rlim_max = value;
    }

    if (soft) {
        ls.rlim_cur = value;

        // Do not attempt to set the soft limit higher than the hard limit.
        if ((value == RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY) ||
            (value != RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY && value > ls.rlim_max)) {
            ls.rlim_cur = ls.rlim_max;
        }
    }

    if (setrlimit(resource, &ls)) {
        if (errno == EPERM)
            streams.err.append_format(
                L"ulimit: Permission denied when changing resource of type '%ls'\n",
                get_desc(resource));
        else
            builtin_wperror(L"ulimit", streams);
        return 1;
    }
    return 0;
}
示例#2
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, wcstring_list_t &val, int scope )
{
	size_t i;
	int retcode = 0;
	const wchar_t *val_str=NULL;
		
	if( is_path_variable( key ) )
	{
		int error = 0;
		
		for( i=0; i< val.size() ; i++ )
		{
			int show_perror = 0;
			int show_hint = 0;
			
			struct stat buff;
			const wchar_t *dir = val[i].c_str();
			
			if( wstat( dir, &buff ) )
			{
				error = 1;
				show_perror = 1;
			}

			if( !( S_ISDIR(buff.st_mode) ) )
			{
				error = 1;
				
			}
			
			if( error )
			{
				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);
			}
			
			if( error )
			{
				break;
			}
			
		}

		if( error )
		{
			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;
}
示例#3
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;
}
示例#4
0
/// The  source builtin, sometimes called `.`. Evaluates the contents of a file in the current
/// context.
int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
    ASSERT_IS_MAIN_THREAD();
    const wchar_t *cmd = argv[0];
    int argc = builtin_count_args(argv);
    help_only_cmd_opts_t opts;

    int optind;
    int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams);
    if (retval != STATUS_CMD_OK) return retval;

    if (opts.print_help) {
        builtin_print_help(parser, streams, cmd, streams.out);
        return STATUS_CMD_OK;
    }

    int fd;
    struct stat buf;
    const wchar_t *fn, *fn_intern;

    if (argc == optind || wcscmp(argv[optind], L"-") == 0) {
        // Either a bare `source` which means to implicitly read from stdin or an explicit `-`.
        if (argc == optind && !streams.stdin_is_directly_redirected) {
            // Don't implicitly read from the terminal.
            return STATUS_CMD_ERROR;
        }
        fn = L"-";
        fn_intern = fn;
        fd = dup(streams.stdin_fd);
    } else {
        if ((fd = wopen_cloexec(argv[optind], O_RDONLY)) == -1) {
            streams.err.append_format(_(L"%ls: Error encountered while sourcing file '%ls':\n"),
                                      cmd, argv[optind]);
            builtin_wperror(cmd, streams);
            return STATUS_CMD_ERROR;
        }

        if (fstat(fd, &buf) == -1) {
            close(fd);
            streams.err.append_format(_(L"%ls: Error encountered while sourcing file '%ls':\n"),
                                      cmd, argv[optind]);
            builtin_wperror(L"source", streams);
            return STATUS_CMD_ERROR;
        }

        if (!S_ISREG(buf.st_mode)) {
            close(fd);
            streams.err.append_format(_(L"%ls: '%ls' is not a file\n"), cmd, argv[optind]);
            return STATUS_CMD_ERROR;
        }

        fn_intern = intern(argv[optind]);
    }

    const source_block_t *sb = parser.push_block<source_block_t>(fn_intern);
    reader_push_current_filename(fn_intern);

    // This is slightly subtle. If this is a bare `source` with no args then `argv + optind` already
    // points to the end of argv. Otherwise we want to skip the file name to get to the args if any.
    env_set_argv(argv + optind + (argc == optind ? 0 : 1));

    retval = reader_read(fd, streams.io_chain ? *streams.io_chain : io_chain_t());

    parser.pop_block(sb);

    if (retval != STATUS_CMD_OK) {
        streams.err.append_format(_(L"%ls: Error while reading file '%ls'\n"), cmd,
                                  fn_intern == intern_static(L"-") ? L"<stdin>" : fn_intern);
    } else {
        retval = proc_get_last_status();
    }

    // Do not close fd after calling reader_read. reader_read automatically closes it before calling
    // eval.
    reader_pop_current_filename();
    return retval;
}
示例#5
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, 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;
}
示例#6
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;
}