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 ); }
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 ); }
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 ); }