hashify_input_t hashify_parse_command_line( const char* const* cmdline ) { hashify_input_t input = {0}; int arg, asize; input.check_only = false; error_context_push( "parsing command line", "" ); for( arg = 1, asize = array_size( cmdline ); arg < asize; ++arg ) { if( string_equal( cmdline[arg], "--validate" ) ) { input.check_only = true; continue; } else if( string_equal( cmdline[arg], "--generate-string" ) ) { if( arg < asize - 1 ) { ++arg; array_push( input.strings, string_clone( cmdline[arg] ) ); } continue; } else if( string_equal( cmdline[arg], "--" ) ) break; //Stop parsing cmdline options else if( ( string_length( cmdline[arg] ) > 2 ) && string_equal_substr( cmdline[arg], "--", 2 ) ) continue; //Cmdline argument not parsed here array_push( input.files, string_clone( cmdline[arg] ) ); } error_context_pop(); return input; }
int bin2hex_process_files( char const* const* input, char const* const* output, int columns ) { int result = BIN2HEX_RESULT_OK; unsigned int ifile, files_size; for( ifile = 0, files_size = array_size( input ); ( result == BIN2HEX_RESULT_OK ) && ( ifile < files_size ); ++ifile ) { char* input_filename = 0; char* output_filename = 0; stream_t* input_file = 0; stream_t* output_file = 0; input_filename = path_clean( string_clone( input[ifile] ), path_is_absolute( input[ifile] ) ); error_context_push( "parsing file", input_filename ); output_filename = path_clean( string_clone( output[ifile] ), path_is_absolute( output[ifile] ) ); log_infof( 0, "bin2hex %s -> %s", input_filename, output_filename ); input_file = stream_open( input_filename, STREAM_IN | STREAM_BINARY ); if( !input_file ) { log_warnf( 0, WARNING_BAD_DATA, "Unable to open input file: %s", input_filename ); result = BIN2HEX_RESULT_MISSING_INPUT_FILE; } else { output_file = stream_open( output_filename, STREAM_OUT ); if( !output_file ) { log_warnf( 0, WARNING_BAD_DATA, "Unable to open output file: %s", output_filename ); result = BIN2HEX_RESULT_UNABLE_TO_OPEN_OUTPUT_FILE; } } if( input_file && output_file ) result = bin2hex_process_file( input_file, output_file, columns ); stream_deallocate( input_file ); stream_deallocate( output_file ); string_deallocate( output_filename ); error_context_pop(); string_deallocate( input_filename ); } if( ( result == BIN2HEX_RESULT_OK ) && ( files_size > 0 ) ) log_info( 0, "All files generated" ); return result; }
char* path_merge( const char* first, const char* second ) { char* merged; if( !first ) merged = string_clone( second ); else if( !second ) merged = string_clone( first ); else { merged = string_format( "%s/", first ); merged = string_append( merged, second ); } merged = path_clean( merged, path_is_absolute( first ) ); return merged; }
void process_set_arguments(process_t* proc, const string_const_t* args, size_t num) { size_t ia; string_array_deallocate(proc->args); for (ia = 0; ia < num; ++ia) array_push(proc->args, string_clone(args[ia].str, args[ia].length)); }
struct string *strlist_clone(struct strlist *list, size_t index) { if (index >= list->size) return NULL; return string_clone(list->items[index]); }
void process_set_working_directory( process_t* proc, const char* path ) { if( !proc ) return; string_deallocate( proc->wd ); proc->wd = string_clone( path ); }
void process_set_executable_path( process_t* proc, const char* path ) { if( !proc ) return; string_deallocate( proc->path ); proc->path = string_clone( path ); }
bin2hex_input_t bin2hex_parse_command_line( char const* const* cmdline ) { bin2hex_input_t input = {0}; int arg, asize; error_context_push( "parsing command line", "" ); for( arg = 1, asize = array_size( cmdline ); arg < asize; ++arg ) { if( string_equal( cmdline[arg], "--columns" ) ) { if( arg < ( asize - 1 ) ) input.columns = string_to_int( cmdline[++arg] ); } else if( string_equal( cmdline[arg], "--" ) ) break; //Stop parsing cmdline options else if( ( string_length( cmdline[arg] ) > 2 ) && string_equal_substr( cmdline[arg], "--", 2 ) ) continue; //Cmdline argument not parsed here else { array_push( input.input_files, string_clone( cmdline[arg] ) ); array_push( input.output_files, string_format( "%s.hex", cmdline[arg] ) ); } } error_context_pop(); return input; }
char* path_file_name( const char* path ) { unsigned int end = string_find_last_of( path, "/\\", STRING_NPOS ); if( end == STRING_NPOS ) return string_clone( path ); return string_substr( path, end + 1, STRING_NPOS ); }
shaderparameter_t* shader_get_param(shaderprogram_t* program, const char* name, ShaderParamType type) { GLint paramIndex = 0; GLint paramSize = 0; GLenum paramType; switch(type) { default: case ShaderParamType_Uniform: { GLsizei nameLength; paramIndex = glGetUniformLocation(program->program, name); glGetActiveUniform(program->program, paramIndex, 0, &nameLength, ¶mSize, ¶mType, nullptr); FOUNDATION_ASSERT(paramSize > 0); } case ShaderParamType_UniformBlock: { paramIndex = glGetUniformBlockIndex(program->program, name); glGetActiveUniformBlockiv(program->program, paramIndex, GL_UNIFORM_BLOCK_DATA_SIZE, ¶mSize); FOUNDATION_ASSERT(paramSize > 0); } } shaderparameter_t* param = (shaderparameter_t*) memory_allocate(sizeof(shaderparameter_t), 4, MEMORY_PERSISTENT); param->index = paramIndex; param->size = paramSize; param->gltype = paramType; param->name = string_clone(name); param->type = type; return param; }
static stream_t* _stream_std_clone( stream_t* stream ) { stream_std_t* clone = memory_allocate_zero_context( MEMORYCONTEXT_STREAM, sizeof( stream_std_t ), 8, MEMORY_PERSISTENT ); memcpy( clone, stream, sizeof( stream_std_t ) ); clone->path = string_clone( stream->path ); return (stream_t*)clone; }
char* path_file_extension( const char* path ) { unsigned int start = string_find_last_of( path, "/\\", STRING_NPOS ); unsigned int end = string_rfind( path, '.', STRING_NPOS ); if( ( end != STRING_NPOS ) && ( ( start == STRING_NPOS ) || ( end > start ) ) ) return string_substr( path, end + 1, STRING_NPOS ); return string_clone( "" ); }
static obj_t string_copy_fn(obj_t args, Reporter rep) { string str; if (!args_match(rep, args, 1, is_string)) return unspecific; str = fetch_string(list_ref(args, 0)); return make_string(string_clone(str)); }
void process_set_verb( process_t* proc, const char* verb ) { if( !proc ) return; #if FOUNDATION_PLATFORM_WINDOWS string_deallocate( proc->verb ); proc->verb = string_clone( verb ); #endif }
char* path_prepend( char* tail, const char* base ) { if( !tail ) return path_clean( string_clone( base ), path_is_absolute( base ) ); tail = string_prepend( tail, "/" ); tail = string_prepend( tail, base ); tail = path_clean( tail, path_is_absolute( tail ) ); return tail; }
char* path_append( char* base, const char* tail ) { if( !base ) return path_clean( string_clone( tail ), path_is_absolute( tail ) ); base = string_append( base, "/" ); base = string_append( base, tail ); base = path_clean( base, path_is_absolute( base ) ); return base; }
void process_set_arguments( process_t* proc, const char** args, unsigned int num ) { unsigned int ia; if( !proc ) return; string_array_deallocate( proc->args ); for( ia = 0; ia < num; ++ia ) array_push( proc->args, string_clone( args[ia] ) ); }
char* path_subdirectory_name( const char* path, const char* root ) { char* subpath; char* testpath; char* testroot; char* pathofpath; unsigned int pathprotocol, rootprotocol; char* cpath = string_clone( path ); char* croot = string_clone( root ); cpath = path_clean( cpath, path_is_absolute( cpath ) ); croot = path_clean( croot, path_is_absolute( croot ) ); pathofpath = path_directory_name( cpath ); testpath = pathofpath; pathprotocol = string_find_string( testpath, "://", 0 ); if( pathprotocol != STRING_NPOS ) testpath += pathprotocol + 2; // add two to treat as absolute path testroot = croot; rootprotocol = string_find_string( testroot, "://", 0 ); if( rootprotocol != STRING_NPOS ) testroot += rootprotocol + 2; if( ( rootprotocol != STRING_NPOS ) && ( ( pathprotocol == STRING_NPOS ) || ( pathprotocol != rootprotocol ) || !string_equal_substr( cpath, croot, rootprotocol ) ) ) subpath = string_allocate( 0 ); else if( !string_equal_substr( testpath, testroot, string_length( testroot ) ) ) subpath = string_allocate( 0 ); else { char* filename = path_file_name( cpath ); subpath = string_substr( testpath, string_length( testroot ), STRING_NPOS ); subpath = path_clean( path_append( subpath, filename ), false ); string_deallocate( filename ); } string_deallocate( pathofpath ); string_deallocate( cpath ); string_deallocate( croot ); return subpath; }
DECLARE_TEST(environment, workingdir) { char buffer[BUILD_MAX_PATHLEN]; string_const_t working_dir = environment_current_working_directory(); string_const_t new_working_dir = path_directory_name(STRING_ARGS(working_dir)); string_t working_dir_copy = string_clone(STRING_ARGS(working_dir)); string_t new_working_dir_copy; if (string_equal(STRING_ARGS(working_dir), STRING_CONST("/"))) { string_t tmpwork = path_make_temporary(buffer, sizeof(buffer)); new_working_dir = path_directory_name(STRING_ARGS(tmpwork)); } new_working_dir_copy = string_clone(STRING_ARGS(new_working_dir)); new_working_dir = string_to_const(new_working_dir_copy); EXPECT_CONSTSTRINGNE(working_dir, new_working_dir); #if FOUNDATION_PLATFORM_PNACL EXPECT_FALSE(environment_set_current_working_directory(STRING_ARGS(new_working_dir))); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); #else EXPECT_TRUE(environment_set_current_working_directory(STRING_ARGS(new_working_dir))); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), new_working_dir); environment_set_current_working_directory(STRING_ARGS(working_dir_copy)); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); { log_enable_stdout(false); bool ret = environment_set_current_working_directory(STRING_CONST("/invalid/path/which/does/not/exist")); log_enable_stdout(true); EXPECT_FALSE(ret); } EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); #endif string_deallocate(new_working_dir_copy.str); string_deallocate(working_dir_copy.str); return 0; }
hashify_input_t hashify_parse_command_line(const string_const_t* cmdline) { hashify_input_t input; size_t arg, asize; memset(&input, 0, sizeof(input)); input.check_only = false; error_context_push(STRING_CONST("parsing command line"), STRING_CONST("")); for (arg = 1, asize = array_size(cmdline); arg < asize; ++arg) { if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--help"))) { hashify_print_usage(); continue; } else if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--validate"))) { input.check_only = true; continue; } else if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--generate-string"))) { if (arg < asize - 1) { ++arg; array_push(input.strings, string_clone(STRING_ARGS(cmdline[arg]))); } continue; } else if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--debug"))) { log_set_suppress(0, ERRORLEVEL_NONE); continue; } else if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--"))) break; //Stop parsing cmdline options else if ((cmdline[arg].length > 2) && string_equal(cmdline[arg].str, 2, STRING_CONST("--"))) continue; //Cmdline argument not parsed here array_push(input.files, string_clone(STRING_ARGS(cmdline[arg]))); } error_context_pop(); if (array_size(cmdline) <= 1) hashify_print_usage(); return input; }
stream_t* stream_open_stdin( void ) { stream_std_t* stream = memory_allocate_zero_context( MEMORYCONTEXT_STREAM, sizeof( stream_std_t ), 8, MEMORY_PERSISTENT ); _stream_initialize( (stream_t*)stream, system_byteorder() ); stream->sequential = 1; stream->mode = STREAM_IN; stream->type = STREAMTYPE_STDSTREAM; stream->vtable = &_stream_stdin_vtable; stream->path = string_clone( "stdin://" ); stream->std = stdin; return (stream_t*)stream; }
static NOINLINE char* _expand_string( hash_t section_current, char* str ) { char* expanded; char* variable; unsigned int var_pos, var_end_pos, variable_length, separator, var_offset; hash_t section, key; expanded = str; var_pos = string_find_string( expanded, "$(", 0 ); while( var_pos != STRING_NPOS ) { var_end_pos = string_find( expanded, ')', var_pos + 2 ); FOUNDATION_ASSERT_MSG( var_end_pos != STRING_NPOS, "Malformed config variable statement" ); variable = string_substr( expanded, var_pos, ( var_end_pos != STRING_NPOS ) ? ( 1 + var_end_pos - var_pos ) : STRING_NPOS ); section = section_current; key = 0; variable_length = string_length( variable ); separator = string_find( variable, ':', 0 ); if( separator != STRING_NPOS ) { if( separator != 2 ) section = hash( variable + 2, separator - 2 ); var_offset = separator + 1; } else { var_offset = 2; } key = hash( variable + var_offset, variable_length - ( var_offset + ( variable[ variable_length - 1 ] == ')' ? 1 : 0 ) ) ); if( expanded == str ) expanded = string_clone( str ); if( section != HASH_ENVIRONMENT ) expanded = string_replace( expanded, variable, config_string( section, key ), false ); else expanded = string_replace( expanded, variable, _expand_environment( key, variable + var_offset ), false ); string_deallocate( variable ); var_pos = string_find_string( expanded, "$(", 0 ); } #if BUILD_ENABLE_DEBUG_CONFIG if( str != expanded ) log_debugf( HASH_CONFIG, "Expanded config value \"%s\" to \"%s\"", str, expanded ); #endif return expanded; }
blast_reader_t* blast_reader_open(string_t source) { void* addr; int64_t size; blast_reader_t* reader; int fd; fd = _open(source.str, O_RDONLY); if (fd == 0) return 0; size = _lseek(fd, 0, SEEK_END); if (size <= 0) { _close(fd); return 0; } _lseek(fd, 0, SEEK_SET); addr = memory_allocate(HASH_BLAST, (size_t)size, 0, MEMORY_PERSISTENT); _read(fd, addr, (int)size); _close(fd); /*addr = mmap( 0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0 ); if( addr == MAP_FAILED ) { int err = system_error(); log_warnf( HASH_BLAST, WARNING_SYSTEM_CALL_FAIL, "Unable to mmap file '%s' (%d) size %d: %s (%d)", source, fd, size, system_error_message( err ), err ); close( fd ); return 0; } log_infof( HASH_BLAST, "Mapped '%s' size %lld to memory region 0x%" PRIfixPTR, source, size, addr );*/ reader = memory_allocate(HASH_BLAST, sizeof(blast_reader_t), 0, MEMORY_PERSISTENT | MEMORY_ZERO_INITIALIZED); string_const_t filename = path_file_name(STRING_ARGS(source)); reader->name = string_clone(STRING_ARGS(filename)); reader->data = addr; //reader->id = fd; reader->size = (uint64_t)size; reader->cache = blast_reader_cache; reader->uncache = blast_reader_uncache; reader->map = blast_reader_map; reader->unmap = blast_reader_unmap; return reader; }
char* path_directory_name( const char* path ) { char* pathname; unsigned int pathprotocol; unsigned int pathstart = 0; unsigned int end = string_find_last_of( path , "/\\", STRING_NPOS ); if( end == 0 ) return string_clone( "/" ); if( end == STRING_NPOS ) return string_allocate( 0 ); pathprotocol = string_find_string( path, "://", 0 ); if( pathprotocol != STRING_NPOS ) pathstart = pathprotocol +=2; // add two to treat as absolute path pathname = string_substr( path, pathstart, end - pathstart ); pathname = path_clean( pathname, path_is_absolute( pathname ) ); return pathname; }
void config_set_string( hash_t section, hash_t key, const char* value ) { config_key_t* key_val = config_key( section, key, true ); if( !FOUNDATION_VALIDATE( key_val ) ) return; if( key_val->expanded != key_val->sval ) string_deallocate( key_val->expanded ); if( ( key_val->type != CONFIGVALUE_STRING_CONST ) && ( key_val->type != CONFIGVALUE_STRING_CONST_VAR ) ) string_deallocate( key_val->sval ); key_val->sval = string_clone( value ); key_val->expanded = 0; key_val->type = ( ( string_find_string( key_val->sval, "$(", 0 ) != STRING_NPOS ) ? CONFIGVALUE_STRING_VAR : CONFIGVALUE_STRING ); if( key_val->type == CONFIGVALUE_STRING ) { bool is_true = string_equal( key_val->sval, "true" ); key_val->bval = ( string_equal( key_val->sval, "false" ) || string_equal( key_val->sval, "0" ) || !string_length( key_val->sval ) ) ? false : true; key_val->ival = is_true ? 1 : _config_string_to_int( key_val->sval ); key_val->rval = is_true ? REAL_C(1.0) : _config_string_to_real( key_val->sval ); } }
PluginData* PluginHandler_reloadPlugin(PluginData* pluginData) { const char* filename = pluginData->filename; const char* fullName = string_clone(pluginData->fullFilename); printf("removing plugin...\n"); removePlugin(pluginData); printf("adding plugin...%s\n", filename); PluginHandler_addPlugin(OBJECT_DIR, filename); printf("finding plugin\n"); printf("trying to find %s\n", fullName); PluginData* newPluginData = PluginHandler_findPluginByFilename(fullName); printf("found plugin %p\n", newPluginData); return newPluginData; }
DECLARE_TEST( string, prepend ) { const char* nullstr = 0; const char* emptystr = ""; const char* shortstr = "short"; const char* longstr = "long long long long long long long long long"; char* val; val = 0; val = string_prepend( val, nullstr ); EXPECT_STREQ( val, "" ); string_deallocate( val ); val = 0; val = string_prepend( val, emptystr ); EXPECT_STREQ( val, "" ); string_deallocate( val ); val = string_clone( emptystr ); val = string_prepend( val, nullstr ); EXPECT_STREQ( val, "" ); string_deallocate( val ); val = string_clone( emptystr ); val = string_prepend( val, emptystr ); EXPECT_STREQ( val, "" ); string_deallocate( val ); val = 0; val = string_prepend( val, shortstr ); EXPECT_STREQ( val, "short" ); string_deallocate( val ); val = string_clone( shortstr ); val = string_prepend( val, nullstr ); EXPECT_STREQ( val, "short" ); string_deallocate( val ); val = string_clone( emptystr ); val = string_prepend( val, shortstr ); EXPECT_STREQ( val, "short" ); string_deallocate( val ); val = string_clone( shortstr ); val = string_prepend( val, emptystr ); EXPECT_STREQ( val, "short" ); string_deallocate( val ); val = string_clone( shortstr ); val = string_prepend( val, shortstr ); EXPECT_STREQ( val, "shortshort" ); string_deallocate( val ); val = 0; val = string_prepend( val, longstr ); EXPECT_STREQ( val, "long long long long long long long long long" ); string_deallocate( val ); val = string_clone( longstr ); val = string_prepend( val, nullstr ); EXPECT_STREQ( val, "long long long long long long long long long" ); string_deallocate( val ); val = string_clone( emptystr ); val = string_prepend( val, longstr ); EXPECT_STREQ( val, "long long long long long long long long long" ); string_deallocate( val ); val = string_clone( longstr ); val = string_prepend( val, emptystr ); EXPECT_STREQ( val, "long long long long long long long long long" ); string_deallocate( val ); val = string_clone( shortstr ); val = string_prepend( val, longstr ); EXPECT_STREQ( val, "long long long long long long long long longshort" ); string_deallocate( val ); val = string_clone( longstr ); val = string_prepend( val, shortstr ); EXPECT_STREQ( val, "shortlong long long long long long long long long" ); string_deallocate( val ); val = string_clone( longstr ); val = string_prepend( val, longstr ); EXPECT_STREQ( val, "long long long long long long long long longlong long long long long long long long long" ); string_deallocate( val ); return 0; }
int process_spawn( process_t* proc ) { static char unescaped[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.:/\\"; int i, num_args; int size; #if FOUNDATION_PLATFORM_WINDOWS wchar_t* wcmdline; wchar_t* wwd; char* cmdline = 0; #endif if( !proc ) return PROCESS_INVALID_ARGS; proc->code = PROCESS_INVALID_ARGS; if( !string_length( proc->path ) ) return proc->code; //Always escape path on Windows platforms #if FOUNDATION_PLATFORM_POSIX if( string_find_first_not_of( proc->path, unescaped, 0 ) != STRING_NPOS ) #endif { if( proc->path[0] != '"' ) proc->path = string_prepend( proc->path, "\"" ); if( proc->path[ string_length( proc->path ) - 1 ] != '"' ) proc->path = string_append( proc->path, "\"" ); } size = array_size( proc->args ); for( i = 0, num_args = 0; i < size; ++i ) { char* arg = proc->args[i]; if( !string_length( arg ) ) continue; ++num_args; if( string_find_first_not_of( arg, unescaped, 0 ) != STRING_NPOS ) { if( arg[0] != '"' ) { //Check if we need to escape " characters unsigned int pos = string_find( arg, '"', 0 ); while( pos != STRING_NPOS ) { if( arg[ pos - 1 ] != '\\' ) { char* escarg = string_substr( arg, 0, pos ); char* left = string_substr( arg, pos, STRING_NPOS ); escarg = string_append( escarg, "\\" ); escarg = string_append( escarg, left ); string_deallocate( left ); string_deallocate( arg ); arg = escarg; } pos = string_find( arg, '"', pos + 2 ); } arg = string_prepend( arg, "\"" ); arg = string_append( arg, "\"" ); proc->args[i] = arg; } } } #if FOUNDATION_PLATFORM_WINDOWS # ifndef SEE_MASK_NOASYNC # define SEE_MASK_NOASYNC 0x00000100 # endif if( !( proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE ) ) //Don't prepend exe path to parameters if using ShellExecute cmdline = string_clone( proc->path ); //Build command line string for( i = 0; i < size; ++i ) { char* arg = proc->args[i]; if( !string_length( arg ) ) continue; if( cmdline ) cmdline = string_append( cmdline, " " ); cmdline = string_append( cmdline, arg ); } if( !string_length( proc->wd ) ) proc->wd = string_clone( environment_current_working_directory() ); wcmdline = wstring_allocate_from_string( cmdline, 0 ); wwd = wstring_allocate_from_string( proc->wd, 0 ); if( proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE ) { SHELLEXECUTEINFOW sei; wchar_t* wverb; wchar_t* wpath; wverb = ( proc->verb && string_length( proc->verb ) ) ? wstring_allocate_from_string( proc->verb, 0 ) : 0; wpath = wstring_allocate_from_string( proc->path, 0 ); ZeroMemory( &sei, sizeof( sei ) ); sei.cbSize = sizeof(SHELLEXECUTEINFOW); sei.hwnd = 0; sei.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; sei.lpVerb = wverb; sei.lpFile = wpath; sei.lpParameters = wcmdline; sei.lpDirectory = wwd; sei.nShow = SW_SHOWNORMAL; if( !( proc->flags & PROCESS_CONSOLE ) ) sei.fMask |= SEE_MASK_NO_CONSOLE; if( proc->flags & PROCESS_STDSTREAMS ) log_warnf( 0, WARNING_UNSUPPORTED, "Unable to redirect standard in/out through pipes when using ShellExecute for process spawning" ); log_debugf( 0, "Spawn process (ShellExecute): %s %s", proc->path, cmdline ); if( !ShellExecuteExW( &sei ) ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to spawn process (ShellExecute) for executable '%s': %s", proc->path, system_error_message( GetLastError() ) ); } else { proc->hp = sei.hProcess; proc->ht = 0; proc->code = 0; } wstring_deallocate( wverb ); wstring_deallocate( wpath ); } else { STARTUPINFOW si; PROCESS_INFORMATION pi; BOOL inherit_handles = FALSE; memset( &si, 0, sizeof( si ) ); memset( &pi, 0, sizeof( pi ) ); si.cb = sizeof( si ); if( proc->flags & PROCESS_STDSTREAMS ) { proc->pipeout = pipe_allocate(); proc->pipein = pipe_allocate(); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdOutput = pipe_write_handle( proc->pipeout ); si.hStdError = pipe_write_handle( proc->pipeout ); si.hStdInput = pipe_read_handle( proc->pipein ); //Don't inherit wrong ends of pipes SetHandleInformation( pipe_read_handle( proc->pipeout ), HANDLE_FLAG_INHERIT, 0 ); SetHandleInformation( pipe_write_handle( proc->pipein ), HANDLE_FLAG_INHERIT, 0 ); inherit_handles = TRUE; } log_debugf( 0, "Spawn process (CreateProcess): %s %s", proc->path, cmdline ); if( !CreateProcessW( 0/*wpath*/, wcmdline, 0, 0, inherit_handles, ( proc->flags & PROCESS_CONSOLE ) ? CREATE_NEW_CONSOLE : 0, 0, wwd, &si, &pi ) ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to spawn process (CreateProcess) for executable '%s': %s", proc->path, system_error_message( GetLastError() ) ); stream_deallocate( proc->pipeout ); stream_deallocate( proc->pipein ); proc->pipeout = 0; proc->pipein = 0; } else { proc->hp = pi.hProcess; proc->ht = pi.hThread; proc->code = 0; } if( proc->pipeout ) pipe_close_write( proc->pipeout ); if( proc->pipein ) pipe_close_read( proc->pipein ); } wstring_deallocate( wcmdline ); wstring_deallocate( wwd ); string_deallocate( cmdline ); if( proc->code < 0 ) return proc->code; //Error #endif #if FOUNDATION_PLATFORM_MACOSX if( proc->flags & PROCESS_OSX_USE_OPENAPPLICATION ) { proc->pid = 0; LSApplicationParameters params; ProcessSerialNumber psn; FSRef* fsref = memory_allocate( 0, sizeof( FSRef ), 0, MEMORY_TEMPORARY | MEMORY_ZERO_INITIALIZED ); memset( ¶ms, 0, sizeof( LSApplicationParameters ) ); memset( &psn, 0, sizeof( ProcessSerialNumber ) ); char* pathstripped = string_strip( string_clone( proc->path ), "\"" ); OSStatus status = 0; status = FSPathMakeRef( (uint8_t*)pathstripped, fsref, 0 ); if( status < 0 ) { pathstripped = string_append( pathstripped, ".app" ); status = FSPathMakeRef( (uint8_t*)pathstripped, fsref, 0 ); } CFStringRef* args = 0; for( i = 0, size = array_size( proc->args ); i < size; ++i ) //App gets executable path automatically, don't include array_push( args, CFStringCreateWithCString( 0, proc->args[i], kCFStringEncodingUTF8 ) ); CFArrayRef argvref = CFArrayCreate( 0, (const void**)args, (CFIndex)array_size( args ), 0 ); params.flags = kLSLaunchDefaults; params.application = fsref; params.argv = argvref; log_debugf( 0, "Spawn process (LSOpenApplication): %s", pathstripped ); status = LSOpenApplication( ¶ms, &psn ); if( status != 0 ) { proc->code = status; log_warnf( 0, WARNING_BAD_DATA, "Unable to spawn process for executable '%s': %s", proc->path, system_error_message( status ) ); } CFRelease( argvref ); for( i = 0, size = array_size( args ); i < size; ++i ) CFRelease( args[i] ); memory_deallocate( fsref ); string_deallocate( pathstripped ); if( status == 0 ) { pid_t pid = 0; GetProcessPID( &psn, &pid ); proc->pid = pid; //Always "detached" with LSOpenApplication, not a child process at all //Setup a kqueue to watch when process terminates so we can emulate a wait proc->kq = kqueue(); if( proc->kq < 0 ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to create kqueue for process watch: %s (%d)", proc->kq, system_error_message( proc->kq ) ); proc->kq = 0; } else { struct kevent changes; EV_SET( &changes, (pid_t)pid, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, 0 ); int ret = kevent( proc->kq, &changes, 1, &changes, 1, 0 ); if( ret != 1 ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to setup kqueue for process watch, failed to add event to kqueue (%d)", ret ); close( proc->kq ); proc->kq = 0; } } } goto exit; } #endif #if FOUNDATION_PLATFORM_POSIX //Insert executable arg at start and null ptr at end int argc = array_size( proc->args ) + 1; array_grow( proc->args, 2 ); for( int arg = argc - 1; arg > 0; --arg ) proc->args[arg] = proc->args[arg-1]; proc->args[0] = string_clone( proc->path ); proc->args[argc] = 0; if( proc->flags & PROCESS_STDSTREAMS ) { proc->pipeout = pipe_allocate(); proc->pipein = pipe_allocate(); } proc->pid = 0; pid_t pid = fork(); if( pid == 0 ) { //Child if( string_length( proc->wd ) ) { log_debugf( 0, "Spawned child process, setting working directory to %s", proc->wd ); environment_set_current_working_directory( proc->wd ); } log_debugf( 0, "Child process executing: %s", proc->path ); if( proc->flags & PROCESS_STDSTREAMS ) { pipe_close_read( proc->pipeout ); dup2( pipe_write_fd( proc->pipeout ), STDOUT_FILENO ); pipe_close_write( proc->pipein ); dup2( pipe_read_fd( proc->pipein ), STDIN_FILENO ); } int code = execv( proc->path, proc->args ); if( code < 0 ) //Will always be true since this point will never be reached if execve() is successful log_warnf( 0, WARNING_BAD_DATA, "Child process failed execve() : %s : %s", proc->path, system_error_message( errno ) ); //Error process_exit( -1 ); } if( pid > 0 ) { log_debugf( 0, "Child process forked, pid %d", pid ); proc->pid = pid; if( proc->pipeout ) pipe_close_write( proc->pipeout ); if( proc->pipein ) pipe_close_read( proc->pipein ); if( proc->flags & PROCESS_DETACHED ) { int cstatus = 0; pid_t err = waitpid( pid, &cstatus, WNOHANG ); if( err == 0 ) { //TODO: Ugly wait to make sure process spawned correctly thread_sleep( 500 ); err = waitpid( pid, &cstatus, WNOHANG ); } if( err > 0 ) { //Process exited, check code proc->code = (int)((char)WEXITSTATUS( cstatus )); log_debugf( 0, "Child process returned: %d", proc->code ); return proc->code; } } } else { //Error proc->code = errno; log_warnf( 0, WARNING_BAD_DATA, "Unable to spawn process: %s : %s", proc->path, system_error_message( proc->code ) ); if( proc->pipeout ) stream_deallocate( proc->pipeout ); if( proc->pipein ) stream_deallocate( proc->pipein ); proc->pipeout = 0; proc->pipein = 0; return proc->code; } #endif #if !FOUNDATION_PLATFORM_WINDOWS && !FOUNDATION_PLATFORM_POSIX FOUNDATION_ASSERT_FAIL( "Process spawning not supported on platform" ); #endif #if FOUNDATION_PLATFORM_MACOSX exit: #endif if( proc->flags & PROCESS_DETACHED ) return PROCESS_STILL_ACTIVE; return process_wait( proc ); }
DECLARE_TEST( string, utility ) { { char* path1 = string_clone( "" ); char* path2 = string_clone( "/" ); char* path3 = string_clone( "/." ); char* path4 = string_clone( "./" ); char* path5 = string_clone( "./." ); char* path6 = string_clone( "././" ); char* path7 = string_clone( "././//" ); char* path8 = string_clone( "././//./////././////.//////.//." ); char* path9 = string_clone( "http://././//./////././////.//////.//." ); char* path10 = string_clone( "" ); char* path11 = string_clone( "\\" ); char* path12 = string_clone( "/\\." ); char* path13 = string_clone( ".\\/" ); char* path14 = string_clone( "./\\." ); char* path15 = string_clone( ".\\.//\\" ); char* path16 = string_clone( ".\\.\\\\\\" ); char* path17 = string_clone( ".\\.\\\\\\.\\\\////\\///\\\\.\\.\\\\\\\\\\.\\\\\\\\\\\\.\\\\." ); char* path18 = string_clone( "http://\\.\\.\\\\\\.\\\\\\\\//\\.\\.\\\\\\\\//\\.\\\\\\\\\\\\.\\\\." ); char* path19 = string_clone( "testing/path/ext" ); char* path20 = string_clone( "testing/path/extend" ); char* path21 = string_clone( "testing/path/extend/dyn" ); char* path22 = string_clone( "testing/./\\\\/\\/./path/././//./extend/\\\\" ); path1 = path_clean( path1, true ); path2 = path_clean( path2, true ); path3 = path_clean( path3, true ); path4 = path_clean( path4, true ); path5 = path_clean( path5, true ); path6 = path_clean( path6, true ); path7 = path_clean( path7, true ); path8 = path_clean( path8, true ); path9 = path_clean( path9, true ); path10 = path_clean( path10, true ); path11 = path_clean( path11, true ); path12 = path_clean( path12, true ); path13 = path_clean( path13, true ); path14 = path_clean( path14, true ); path15 = path_clean( path15, true ); path16 = path_clean( path16, true ); path17 = path_clean( path17, true ); path18 = path_clean( path18, true ); path19 = path_clean( path19, true ); path20 = path_clean( path20, true ); path21 = path_clean( path21, true ); path22 = path_clean( path22, true ); EXPECT_TRUE( string_equal( path1, "/" ) ); EXPECT_TRUE( string_equal( path2, "/" ) ); EXPECT_TRUE( string_equal( path3, "/" ) ); EXPECT_TRUE( string_equal( path4, "/" ) ); EXPECT_TRUE( string_equal( path5, "/" ) ); EXPECT_TRUE( string_equal( path6, "/" ) ); EXPECT_TRUE( string_equal( path7, "/" ) ); EXPECT_TRUE( string_equal( path8, "/" ) ); EXPECT_TRUE( string_equal( path9, "http://" ) ); EXPECT_TRUE( string_equal( path10, "/" ) ); EXPECT_TRUE( string_equal( path11, "/" ) ); EXPECT_TRUE( string_equal( path12, "/" ) ); EXPECT_TRUE( string_equal( path13, "/" ) ); EXPECT_TRUE( string_equal( path14, "/" ) ); EXPECT_TRUE( string_equal( path15, "/" ) ); EXPECT_TRUE( string_equal( path16, "/" ) ); EXPECT_TRUE( string_equal( path17, "/" ) ); EXPECT_TRUE( string_equal( path18, "http://" ) ); EXPECT_TRUE( string_equal( path19, "/testing/path/ext" ) ); EXPECT_TRUE( string_equal( path20, "/testing/path/extend" ) ); EXPECT_TRUE( string_equal( path21, "/testing/path/extend/dyn" ) ); EXPECT_TRUE( string_equal( path22, "/testing/path/extend" ) ); string_deallocate( path1 ); string_deallocate( path2 ); string_deallocate( path3 ); string_deallocate( path4 ); string_deallocate( path5 ); string_deallocate( path6 ); string_deallocate( path7 ); string_deallocate( path8 ); string_deallocate( path9 ); string_deallocate( path10 ); string_deallocate( path11 ); string_deallocate( path12 ); string_deallocate( path13 ); string_deallocate( path14 ); string_deallocate( path15 ); string_deallocate( path16 ); string_deallocate( path17 ); string_deallocate( path18 ); string_deallocate( path19 ); string_deallocate( path20 ); string_deallocate( path21 ); string_deallocate( path22 ); } { char** explodearr = 0; char* explodestr = string_clone( " .,testing, .,utility.,string methods ..., like,,,finds split..merge .,.explode.and. .., ., similar .,,,. " ); char* mergestr = string_clone( " testing merge string " ); char* mergestr2 = string_clone( " ., testing, .merge.string,. " ); char* merged = 0; char** mergearr, **mergearr2, **mergearr3; char* splitstr = string_clone( " testing split" ); char* splitright = 0, *splitleft = 0; char* splitright2 = 0, *splitleft2 = 0; char* substrtest = string_clone( "testing substr" ); char* substr = 0; explodearr = string_explode( explodestr, " ,.", false ); mergearr = string_explode( mergestr, " .,", true ); mergearr2 = string_explode( mergestr, " .,", false ); mergearr3 = string_explode( mergestr, " .,", true ); merged = string_merge( (const char* const*)mergearr, array_size( mergearr ), " " ); string_split( splitstr, " ", &splitleft, &splitright, false ); string_split( splitstr, " ", &splitleft2, &splitright2, true ); EXPECT_EQ( array_size( explodearr ), 11 ); EXPECT_TRUE( string_equal( explodearr[0], "testing" ) ); EXPECT_TRUE( string_equal( explodearr[1], "utility" ) ); EXPECT_TRUE( string_equal( explodearr[2], "string" ) ); EXPECT_TRUE( string_equal( explodearr[3], "methods" ) ); EXPECT_TRUE( string_equal( explodearr[4], "like" ) ); EXPECT_TRUE( string_equal( explodearr[5], "finds" ) ); EXPECT_TRUE( string_equal( explodearr[6], "split" ) ); EXPECT_TRUE( string_equal( explodearr[7], "merge" ) ); EXPECT_TRUE( string_equal( explodearr[8], "explode" ) ); EXPECT_TRUE( string_equal( explodearr[9], "and" ) ); EXPECT_TRUE( string_equal( explodearr[10], "similar" ) ); EXPECT_EQ( array_size( mergearr ), 12 ); EXPECT_TRUE( string_equal( mergearr[0], "" ) ); EXPECT_TRUE( string_equal( mergearr[1], "" ) ); EXPECT_TRUE( string_equal( mergearr[2], "" ) ); EXPECT_TRUE( string_equal( mergearr[3], "" ) ); EXPECT_TRUE( string_equal( mergearr[4], "testing" ) ); EXPECT_TRUE( string_equal( mergearr[5], "" ) ); EXPECT_TRUE( string_equal( mergearr[6], "" ) ); EXPECT_TRUE( string_equal( mergearr[7], "merge" ) ); EXPECT_TRUE( string_equal( mergearr[8], "string" ) ); EXPECT_TRUE( string_equal( mergearr[9], "" ) ); EXPECT_TRUE( string_equal( mergearr[10], "" ) ); EXPECT_TRUE( string_equal( mergearr[11], "" ) ); EXPECT_EQ( array_size( mergearr2 ), 3 ); EXPECT_TRUE( string_equal( mergearr2[0], "testing" ) ); EXPECT_TRUE( string_equal( mergearr2[1], "merge" ) ); EXPECT_TRUE( string_equal( mergearr2[2], "string" ) ); EXPECT_TRUE( string_equal( merged, mergestr ) ); EXPECT_EQ( array_size( mergearr3 ), 12 ); EXPECT_TRUE( string_equal( mergearr3[0], "" ) ); EXPECT_TRUE( string_equal( mergearr3[1], "" ) ); EXPECT_TRUE( string_equal( mergearr3[2], "" ) ); EXPECT_TRUE( string_equal( mergearr3[3], "" ) ); EXPECT_TRUE( string_equal( mergearr3[4], "testing" ) ); EXPECT_TRUE( string_equal( mergearr3[5], "" ) ); EXPECT_TRUE( string_equal( mergearr3[6], "" ) ); EXPECT_TRUE( string_equal( mergearr3[7], "merge" ) ); EXPECT_TRUE( string_equal( mergearr3[8], "string" ) ); EXPECT_TRUE( string_equal( mergearr3[9], "" ) ); EXPECT_TRUE( string_equal( mergearr3[10], "" ) ); EXPECT_TRUE( string_equal( mergearr3[11], "" ) ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 4 ), "test" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 14 ), "testing substr" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 20 ), "testing substr" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 20 ), "ting substr" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 11 ), "ting substr" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 1 ), "t" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 0 ), "" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 20, 0 ), "" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 20, 20 ), "" ) ); string_deallocate( substr ); EXPECT_TRUE( string_equal( splitleft, "testing" ) ); EXPECT_TRUE( string_equal( splitright, "split" ) ); EXPECT_TRUE( string_equal( splitleft2, "" ) ); EXPECT_TRUE( string_equal( splitright2, "testing split" ) ); { char* replacestr = string_clone( "testing replace" ); char* replacestr2 = string_clone( "testing replace" ); char* replacestr3 = string_clone( "testing replacelace" ); char* replacestr4 = string_clone( "" ); char* replacestr5 = string_clone( "repppppppppp" ); replacestr = string_replace( replacestr, "rep", "testrep", false ); replacestr2 = string_replace( replacestr2, "rep", "testrep", true ); replacestr3 = string_replace( replacestr3, "replace", "testrep", true ); replacestr4 = string_replace( replacestr4, "foo", "bar", true ); replacestr5 = string_replace( replacestr5, "rep", "re", true ); EXPECT_TRUE( string_equal( replacestr, "testing testreplace" ) ); EXPECT_TRUE( string_equal( replacestr2, "testing testreplace" ) ); EXPECT_TRUE( string_equal( replacestr3, "testing testtestrep" ) ); EXPECT_TRUE( string_equal( replacestr4, "" ) ); EXPECT_TRUE( string_equal( replacestr5, "re" ) ); string_deallocate( replacestr ); string_deallocate( replacestr2 ); string_deallocate( replacestr3 ); string_deallocate( replacestr4 ); string_deallocate( replacestr5 ); } { char* stripstr = string_clone( " testing strip : " ); char* stripstr2 = string_clone( " testing strip : " ); char* stripstr3 = string_clone( " testing strip : " ); stripstr = string_strip( stripstr, " tp: " ); stripstr2 = string_strip( stripstr2, "" ); stripstr3 = string_strip( stripstr3, " tesingrp:" ); EXPECT_TRUE( string_equal( stripstr, "esting stri" ) ); EXPECT_TRUE( string_equal( stripstr2, " testing strip : " ) ); EXPECT_TRUE( string_equal( stripstr3, "" ) ); string_deallocate( stripstr ); string_deallocate( stripstr2 ); string_deallocate( stripstr3 ); } string_array_deallocate( explodearr ); string_deallocate( explodestr ); string_deallocate( mergestr ); string_deallocate( mergestr2 ); string_deallocate( merged ); string_array_deallocate( mergearr ); string_array_deallocate( mergearr2 ); string_array_deallocate( mergearr3 ); string_deallocate( splitstr ); string_deallocate( splitright ); string_deallocate( splitleft ); string_deallocate( splitright2 ); string_deallocate( splitleft2 ); string_deallocate( substrtest ); } { #define SHORTSTRING "short" #define LONGSTRING "long string with dynamic buffer storage but with no real useful data" char* clonestr = string_clone( "" ); char* clonestr2 = string_clone( SHORTSTRING ); char* clonestr3 = string_clone( LONGSTRING ); char* teststr = string_clone( clonestr ); char* teststr2 = string_clone( clonestr2 ); char* teststr3 = string_clone( clonestr3 ); char* concatstr = string_concat( clonestr, teststr ); char* concatstr2 = string_concat( clonestr, teststr2 ); char* concatstr3 = string_concat( teststr2, clonestr ); char* concatstr4 = string_concat( clonestr2, teststr2 ); char* concatstr5 = string_concat( clonestr, teststr3 ); char* concatstr6 = string_concat( teststr3, clonestr ); char* concatstr7 = string_concat( clonestr2, teststr3 ); char* concatstr8 = string_concat( teststr3, clonestr2 ); char* concatstr9 = string_concat( clonestr3, teststr3 ); char* concatstr10 = string_concat( teststr3, clonestr3 ); EXPECT_NE( teststr, clonestr ); EXPECT_TRUE( string_equal( teststr, clonestr ) ); EXPECT_NE( teststr2, clonestr2 ); EXPECT_TRUE( string_equal( teststr2, clonestr2 ) ); EXPECT_NE( teststr3, clonestr3 ); EXPECT_TRUE( string_equal( teststr3, clonestr3 ) ); EXPECT_TRUE( string_equal( concatstr, "" ) ); EXPECT_TRUE( string_equal( concatstr2, SHORTSTRING ) ); EXPECT_TRUE( string_equal( concatstr3, SHORTSTRING ) ); EXPECT_TRUE( string_equal( concatstr4, SHORTSTRING SHORTSTRING ) ); EXPECT_TRUE( string_equal( concatstr5, LONGSTRING ) ); EXPECT_TRUE( string_equal( concatstr6, LONGSTRING ) ); EXPECT_TRUE( string_equal( concatstr7, SHORTSTRING LONGSTRING ) ); EXPECT_TRUE( string_equal( concatstr8, LONGSTRING SHORTSTRING ) ); EXPECT_TRUE( string_equal( concatstr9, LONGSTRING LONGSTRING ) ); EXPECT_TRUE( string_equal( concatstr10, LONGSTRING LONGSTRING ) ); string_deallocate( teststr ); string_deallocate( clonestr ); string_deallocate( teststr2 ); string_deallocate( clonestr2 ); string_deallocate( teststr3 ); string_deallocate( clonestr3 ); string_deallocate( concatstr ); string_deallocate( concatstr2 ); string_deallocate( concatstr3 ); string_deallocate( concatstr4 ); string_deallocate( concatstr5 ); string_deallocate( concatstr6 ); string_deallocate( concatstr7 ); string_deallocate( concatstr8 ); string_deallocate( concatstr9 ); string_deallocate( concatstr10 ); #undef SHORTSTRING #undef LONGSTRING } return 0; }
struct strlist *strlist_append(struct strlist *list, struct string *str) { list = strlist_ensure(list, list->size + 1); list->items[list->size++] = string_clone(str); return list; }