예제 #1
0
/// This handles the common case of setting the entire var to a set of values.
static int set_var_array(const wchar_t *cmd, set_cmd_opts_t &opts, const wchar_t *varname,
                         wcstring_list_t &new_values, int argc, wchar_t **argv, parser_t &parser,
                         io_streams_t &streams) {
    UNUSED(cmd);
    UNUSED(parser);
    UNUSED(streams);

    if (opts.prepend || opts.append) {
        if (opts.prepend) {
            for (int i = 0; i < argc; i++) new_values.push_back(argv[i]);
        }
        auto var_str = parser.vars().get(varname, ENV_DEFAULT);
        wcstring_list_t var_array;
        if (var_str) var_str->to_list(var_array);
        new_values.insert(new_values.end(), var_array.begin(), var_array.end());

        if (opts.append) {
            for (int i = 0; i < argc; i++) new_values.push_back(argv[i]);
        }
    } else {
        for (int i = 0; i < argc; i++) new_values.push_back(argv[i]);
    }

    return STATUS_CMD_OK;
}
예제 #2
0
// IEEE 1003.1 says nothing about what it means for two strings to be "algebraically equal". For
// example, should we interpret 0x10 as 0, 10, or 16? Here we use only base 10 and use wcstoll,
// which allows for leading + and -, and whitespace. This is consistent, albeit a bit more lenient
// since we allow trailing whitespace, with other implementations such as bash.
static bool parse_number(const wcstring &arg, long long *out, wcstring_list_t &errors) {
    *out = fish_wcstoll(arg.c_str());
    if (errno) {
        errors.push_back(format_string(_(L"invalid integer '%ls'"), arg.c_str()));
    }
    return !errno;
}
예제 #3
0
static bool binary_primary_evaluate(test_expressions::token_t token, const wcstring &left, const wcstring &right, wcstring_list_t &errors)
{
    using namespace test_expressions;
    long long left_num, right_num;
    switch (token)
    {
        case test_string_equal:
            return left == right;

        case test_string_not_equal:
            return left != right;

        case test_number_equal:
            return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num == right_num;

        case test_number_not_equal:
            return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num != right_num;

        case test_number_greater:
            return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num > right_num;

        case test_number_greater_equal:
            return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num >= right_num;

        case test_number_lesser:
            return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num < right_num;

        case test_number_lesser_equal:
            return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num <= right_num;

        default:
            errors.push_back(format_string(L"Unknown token type in %s", __func__));
            return false;
    }
}
예제 #4
0
bool unary_operator::evaluate(wcstring_list_t &errors) {
    if (token == test_bang) {
        assert(subject.get());
        return !subject->evaluate(errors);
    }

    errors.push_back(format_string(L"Unknown token type in %s", __func__));
    return false;
}
예제 #5
0
bool combining_expression::evaluate(wcstring_list_t &errors)
{
    switch (token)
    {
        case test_combine_and:
        case test_combine_or:
        {
            /* One-element case */
            if (subjects.size() == 1)
                return subjects.at(0)->evaluate(errors);

            /* Evaluate our lists, remembering that AND has higher precedence than OR. We can visualize this as a sequence of OR expressions of AND expressions. */
            assert(combiners.size() + 1 == subjects.size());
            assert(! subjects.empty());

            size_t idx = 0, max = subjects.size();
            bool or_result = false;
            while (idx < max)
            {
                if (or_result)
                {
                    /* Short circuit */
                    break;
                }

                /* Evaluate a stream of AND starting at given subject index. It may only have one element.  */
                bool and_result = true;
                for (; idx < max; idx++)
                {
                    /* Evaluate it, short-circuiting */
                    and_result = and_result && subjects.at(idx)->evaluate(errors);

                    /* If the combiner at this index (which corresponding to how we combine with the next subject) is not AND, then exit the loop */
                    if (idx + 1 < max && combiners.at(idx) != test_combine_and)
                    {
                        idx++;
                        break;
                    }
                }

                /* OR it in */
                or_result = or_result || and_result;
            }
            return or_result;
        }

        default:
            errors.push_back(format_string(L"Unknown token type in %s", __func__));
            return BUILTIN_TEST_FAIL;

    }
}
예제 #6
0
bool unary_operator::evaluate(wcstring_list_t &errors)
{
    switch (token)
    {
        case test_bang:
            assert(subject.get());
            return ! subject->evaluate(errors);
        default:
            errors.push_back(format_string(L"Unknown token type in %s", __func__));
            return false;

    }
}
예제 #7
0
/**
  Put exported or unexported variables in a string list
*/
void env_universal_common_get_names(wcstring_list_t &lst,
                                    int show_exported,
                                    int show_unexported)
{
    env_var_table_t::const_iterator iter;
    for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
    {
        const wcstring& key = iter->first;
        const var_uni_entry_t *e = iter->second;
        if ((e->exportv && show_exported) ||
                (!e->exportv && show_unexported))
        {
            lst.push_back(key);
        }

    }

}
예제 #8
0
/**
   Read lines of input from the specified file, unescape them and
   insert them into the specified list.
*/
static void read_array( FILE* file, wcstring_list_t &comp )
{
	std::vector<char> buffer;
	int c;
	wchar_t *wcs;

	while( !feof( file ) )
	{
		buffer.clear();

		while( 1 )
		{
			c = getc( file );
			if( c == EOF ) 
			{
				break;
			}

			if( c == '\n' )
			{
				break;
			}

            buffer.push_back(static_cast<char>(c));
		}

		if( ! buffer.empty() )
		{
            buffer.push_back(0);
			
			wcs = str2wcs( &buffer.at(0) );
			if( wcs ) 
			{
                wcstring tmp = wcs;
                if (unescape_string(tmp, 0))
                {
                    comp.push_back(tmp);
				}				
				free( wcs );
			}
		}
	}

}
예제 #9
0
bool combining_expression::evaluate(wcstring_list_t &errors) {
    if (token == test_combine_and || token == test_combine_or) {
        assert(!subjects.empty());  //!OCLINT(multiple unary operator)
        assert(combiners.size() + 1 == subjects.size());

        // One-element case.
        if (subjects.size() == 1) return subjects.at(0)->evaluate(errors);

        // Evaluate our lists, remembering that AND has higher precedence than OR. We can
        // visualize this as a sequence of OR expressions of AND expressions.
        size_t idx = 0, max = subjects.size();
        bool or_result = false;
        while (idx < max) {
            if (or_result) {  // short circuit
                break;
            }

            // Evaluate a stream of AND starting at given subject index. It may only have one
            // element.
            bool and_result = true;
            for (; idx < max; idx++) {
                // Evaluate it, short-circuiting.
                and_result = and_result && subjects.at(idx)->evaluate(errors);

                // If the combiner at this index (which corresponding to how we combine with the
                // next subject) is not AND, then exit the loop.
                if (idx + 1 < max && combiners.at(idx) != test_combine_and) {
                    idx++;
                    break;
                }
            }

            // OR it in.
            or_result = or_result || and_result;
        }
        return or_result;
    }

    errors.push_back(format_string(L"Unknown token type in %s", __func__));
    return BUILTIN_TEST_FAIL;
}
예제 #10
0
static bool unary_primary_evaluate(test_expressions::token_t token, const wcstring &arg,
                                   wcstring_list_t &errors) {
    using namespace test_expressions;
    struct stat buf;
    long long num;
    switch (token) {
        case test_filetype_b: {  // "-b", for block special files
            return !wstat(arg, &buf) && S_ISBLK(buf.st_mode);
        }
        case test_filetype_c: {  // "-c", for character special files
            return !wstat(arg, &buf) && S_ISCHR(buf.st_mode);
        }
        case test_filetype_d: {  // "-d", for directories
            return !wstat(arg, &buf) && S_ISDIR(buf.st_mode);
        }
        case test_filetype_e: {  // "-e", for files that exist
            return !wstat(arg, &buf);
        }
        case test_filetype_f: {  // "-f", for for regular files
            return !wstat(arg, &buf) && S_ISREG(buf.st_mode);
        }
        case test_filetype_G: {  // "-G", for check effective group id
            return !wstat(arg, &buf) && getegid() == buf.st_gid;
        }
        case test_filetype_g: {  // "-g", for set-group-id
            return !wstat(arg, &buf) && (S_ISGID & buf.st_mode);
        }
        case test_filetype_h:    // "-h", for symbolic links
        case test_filetype_L: {  // "-L", same as -h
            return !lwstat(arg, &buf) && S_ISLNK(buf.st_mode);
        }
        case test_filetype_O: {  // "-O", for check effective user id
            return !wstat(arg, &buf) && geteuid() == buf.st_uid;
        }
        case test_filetype_p: {  // "-p", for FIFO
            return !wstat(arg, &buf) && S_ISFIFO(buf.st_mode);
        }
        case test_filetype_S: {  // "-S", socket
            return !wstat(arg, &buf) && S_ISSOCK(buf.st_mode);
        }
        case test_filesize_s: {  // "-s", size greater than zero
            return !wstat(arg, &buf) && buf.st_size > 0;
        }
        case test_filedesc_t: {  // "-t", whether the fd is associated with a terminal
            return parse_number(arg, &num, errors) && num == (int)num && isatty((int)num);
        }
        case test_fileperm_r: {  // "-r", read permission
            return !waccess(arg, R_OK);
        }
        case test_fileperm_u: {  // "-u", whether file is setuid
            return !wstat(arg, &buf) && (S_ISUID & buf.st_mode);
        }
        case test_fileperm_w: {  // "-w", whether file write permission is allowed
            return !waccess(arg, W_OK);
        }
        case test_fileperm_x: {  // "-x", whether file execute/search is allowed
            return !waccess(arg, X_OK);
        }
        case test_string_n: {  // "-n", non-empty string
            return !arg.empty();
        }
        case test_string_z: {  // "-z", true if length of string is 0
            return arg.empty();
        }
        default: {
            errors.push_back(format_string(L"Unknown token type in %s", __func__));
            return false;
        }
    }
}