Пример #1
0
int exec_check
(
    string const * command,
    LIST * * pShell,
    int * error_length,
    int * error_max_length
)
{
    /* Default shell does nothing when triggered with an empty or a
     * whitespace-only command so we simply skip running it in that case. We
     * still pass them on to non-default shells as we do not really know what
     * they are going to do with such commands.
     */
    if ( list_empty( *pShell ) )
    {
        char const * s = command->value;
        while ( isspace( *s ) ) ++s;
        if ( !*s )
            return EXEC_CHECK_NOOP;
    }

    /* Check prerequisites for executing raw commands. */
    if ( is_raw_command_request( *pShell ) )
    {
        int const raw_cmd_length = raw_command_length( command->value );
        if ( raw_cmd_length < 0 )
        {
            /* Invalid characters detected - fallback to default shell. */
            list_free( *pShell );
            *pShell = L0;
        }
        else if ( raw_cmd_length > MAX_RAW_COMMAND_LENGTH )
        {
            *error_length = raw_cmd_length;
            *error_max_length = MAX_RAW_COMMAND_LENGTH;
            return EXEC_CHECK_TOO_LONG;
        }
        else
            return raw_cmd_length ? EXEC_CHECK_OK : EXEC_CHECK_NOOP;
    }

    /* Now we know we are using an external shell. Note that there is no need to
     * check for too long command strings when using an external shell since we
     * use a command file and assume no one is going to set up a JAMSHELL format
     * string longer than a few hundred bytes at most which should be well under
     * the total command string limit. Should someone actually construct such a
     * JAMSHELL value it will get reported as an 'invalid parameter'
     * CreateProcessA() Windows API failure which seems like a good enough
     * result for such intentional mischief.
     */

    /* Check for too long command lines. */
    return check_cmd_for_too_long_lines( command->value, maxline(),
        error_length, error_max_length );
}
Пример #2
0
int exec_check
(
    string const * command,
    LIST * * pShell,
    int * error_length,
    int * error_max_length
)
{
    int const is_raw_cmd = is_raw_command_request( *pShell );

    /* We allow empty commands for non-default shells since we do not really
     * know what they are going to do with such commands.
     */
    if ( !command->size && ( is_raw_cmd || list_empty( *pShell ) ) )
        return EXEC_CHECK_NOOP;

    return is_raw_cmd
        ? EXEC_CHECK_OK
        : check_cmd_for_too_long_lines( command->value, MAXLINE, error_length,
            error_max_length );
}
Пример #3
0
void exec_cmd
(
    string const * cmd_orig,
    ExecCmdCallback func,
    void * closure,
    LIST * shell
)
{
    int const slot = get_free_cmdtab_slot();
    int const is_raw_cmd = is_raw_command_request( shell );
    string cmd_local[ 1 ];

    /* Initialize default shell - anything more than /Q/C is non-portable. */
    static LIST * default_shell;
    if ( !default_shell )
        default_shell = list_new( object_new( "cmd.exe /Q/C" ) );

    /* Specifying no shell means requesting the default shell. */
    if ( list_empty( shell ) )
        shell = default_shell;

    if ( DEBUG_EXECCMD )
        if ( is_raw_cmd )
            out_printf( "Executing raw command directly\n" );
        else
        {
            out_printf( "Executing using a command file and the shell: " );
            list_print( shell );
            out_printf( "\n" );
        }

    /* If we are running a raw command directly - trim its leading whitespaces
     * as well as any trailing all-whitespace lines but keep any trailing
     * whitespace in the final/only line containing something other than
     * whitespace).
     */
    if ( is_raw_cmd )
    {
        char const * start = cmd_orig->value;
        char const * p = cmd_orig->value + cmd_orig->size;
        char const * end = p;
        while ( isspace( *start ) ) ++start;
        while ( p > start && isspace( p[ -1 ] ) )
            if ( *--p == '\n' )
                end = p;
        string_new( cmd_local );
        string_append_range( cmd_local, start, end );
        assert( cmd_local->size == raw_command_length( cmd_orig->value ) );
    }
    /* If we are not running a raw command directly, prepare a command file to
     * be executed using an external shell and the actual command string using
     * that command file.
     */
    else
    {
        char const * const cmd_file = prepare_command_file( cmd_orig, slot );
        char const * argv[ MAXARGC + 1 ];  /* +1 for NULL */
        argv_from_shell( argv, shell, cmd_file, slot );
        string_new_from_argv( cmd_local, argv );
    }

    /* Catch interrupts whenever commands are running. */
    if ( !intr_installed )
    {
        intr_installed = 1;
        signal( SIGINT, onintr );
    }

    /* Save input data into the selected running commands table slot. */
    cmdtab[ slot ].func = func;
    cmdtab[ slot ].closure = closure;

    /* Invoke the actual external process using the constructed command line. */
    invoke_cmd( cmd_local->value, slot );

    /* Free our local command string copy. */
    string_free( cmd_local );
}