void file_dirscan( char *dir, scanback func, void *closure ) { PATHNAME f; string filespec[1]; long handle; int ret; struct _find_t finfo[1]; /* First enter directory itself */ memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = dir; f.f_dir.len = strlen(dir); dir = *dir ? dir : "."; /* Special case \ or d:\ : enter it */ string_copy( filespec, dir ); if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' ) (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 ); else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' ) (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 ); else string_push_back( filespec, '/' ); string_push_back( filespec, '*' ); /* Now enter contents of directory */ if( DEBUG_BINDSCAN ) printf( "scan directory %s\n", filespec->value ); /* Time info in dos find_t is not very useful. It consists */ /* of a separate date and time, and putting them together is */ /* not easy. So we leave that to a later stat() call. */ if( !_dos_findfirst( filespec->value, _A_NORMAL|_A_RDONLY|_A_SUBDIR, finfo ) ) { string filename[1]; string_new( filename ); do { f.f_base.ptr = finfo->name; f.f_base.len = strlen( finfo->name ); string_truncate( filename, 0 ); path_build( &f, filename, 0 ); (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 ); } while( !_dos_findnext( finfo ) ); string_free( filename ); } }
void file_build1( PATHNAME * f, string * file ) { if ( DEBUG_SEARCH ) { printf("build file: "); if ( f->f_root.len ) printf( "root = '%.*s' ", f->f_root.len, f->f_root.ptr ); if ( f->f_dir.len ) printf( "dir = '%.*s' ", f->f_dir.len, f->f_dir.ptr ); if ( f->f_base.len ) printf( "base = '%.*s' ", f->f_base.len, f->f_base.ptr ); printf( "\n" ); } /* Start with the grist. If the current grist isn't */ /* surrounded by <>'s, add them. */ if ( f->f_grist.len ) { if ( f->f_grist.ptr[0] != '<' ) string_push_back( file, '<' ); string_append_range( file, f->f_grist.ptr, f->f_grist.ptr + f->f_grist.len ); if ( file->value[file->size - 1] != '>' ) string_push_back( file, '>' ); } }
static void string_new_from_argv( string * result, char const * const * argv ) { assert( argv ); assert( argv[ 0 ] ); string_copy( result, *(argv++) ); while ( *argv ) { string_push_back( result, ' ' ); string_push_back( result, '"' ); string_append( result, *(argv++) ); string_push_back( result, '"' ); } }
void path_build( PATHNAME * f, string * file ) { file_build1( f, file ); /* Do not prepend root if it is '.' or the directory is rooted. */ if ( f->f_root.len && !( f->f_root.len == 1 && f->f_root.ptr[ 0 ] == '.' ) && !( f->f_dir.len && f->f_dir.ptr[ 0 ] == '/' ) #if PATH_DELIM == '\\' && !( f->f_dir.len && f->f_dir.ptr[ 0 ] == '\\' ) && !( f->f_dir.len && f->f_dir.ptr[ 1 ] == ':' ) #endif ) { string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len ); /* If 'root' already ends with a path delimeter, do not add another one. */ if ( !is_path_delim( f->f_root.ptr[ f->f_root.len - 1 ] ) ) string_push_back( file, as_path_delim( f->f_root.ptr[ f->f_root.len ] ) ); } if ( f->f_dir.len ) string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len ); /* Put path separator between dir and file. */ /* Special case for root dir: do not add another path separator. */ if ( f->f_dir.len && ( f->f_base.len || f->f_suffix.len ) #if PATH_DELIM == '\\' && !( f->f_dir.len == 3 && f->f_dir.ptr[ 1 ] == ':' ) #endif && !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[ 0 ] ) ) ) string_push_back( file, as_path_delim( f->f_dir.ptr[ f->f_dir.len ] ) ); if ( f->f_base.len ) string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len ); if ( f->f_suffix.len ) string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len ); if ( f->f_member.len ) { string_push_back( file, '(' ); string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len ); string_push_back( file, ')' ); } }
/** * Get one line from specific stream. */ bool_t string_getline(string_t* pstr_string, FILE* fp_stream) { int n_char = EOF; #ifdef _WIN32 int n_prevchar = EOF; #endif assert(pstr_string != NULL); assert(fp_stream != NULL); clearerr(fp_stream); string_clear(pstr_string); while (!feof(fp_stream) && !ferror(fp_stream) && n_char != '\n' && string_size(pstr_string) < string_max_size(pstr_string)) { n_char = fgetc(fp_stream); if (n_char != '\n' && n_char != EOF) { #ifdef _WIN32 /* new line is '\r\n' in Windows */ if (n_prevchar != EOF) { assert(n_prevchar == '\r'); string_push_back(pstr_string, (char)n_prevchar); n_prevchar = EOF; } if (n_char == '\r') { assert(n_prevchar == EOF); n_prevchar = n_char; } else { string_push_back(pstr_string, (char)n_char); } #else string_push_back(pstr_string, (char)n_char); #endif } } #ifdef _WIN32 if (feof(fp_stream)) { if (n_prevchar != EOF) { assert(n_prevchar == '\r'); string_push_back(pstr_string, (char)n_prevchar); n_prevchar = EOF; } return false; } #endif return (char)n_char == '\n' ? true : false; }
static void import_base_rule( void * r_, void * d_ ) { RULE * r = (RULE *)r_; RULE * ir1; RULE * ir2; struct import_base_data * d = (struct import_base_data *)d_; string qualified_name[ 1 ]; OBJECT * qname; string_new ( qualified_name ); string_append ( qualified_name, object_str( d->base_name ) ); string_push_back( qualified_name, '.' ); string_append ( qualified_name, object_str( r->name ) ); qname = object_new( qualified_name->value ); ir1 = import_rule( r, d->class_module, r->name ); ir2 = import_rule( r, d->class_module, qname ); object_free( qname ); /* Copy 'exported' flag. */ ir1->exported = ir2->exported = r->exported; /* If we are importing a class method, localize it. */ if ( ( r->module == d->base_module ) || ( r->module->class_module && ( r->module->class_module == d->base_module ) ) ) ir1->module = ir2->module = d->class_module; string_free( qualified_name ); }
/** * Get one line from specific stream with delimiter. */ bool_t string_getline_delimiter(string_t* pstr_string, FILE* fp_stream, char c_delimiter) { int n_char = EOF; assert(pstr_string != NULL); assert(fp_stream != NULL); if(c_delimiter == '\n') { return string_getline(pstr_string, fp_stream); } else { clearerr(fp_stream); string_clear(pstr_string); while(!feof(fp_stream) && !ferror(fp_stream) && (char)n_char != c_delimiter && string_size(pstr_string) < string_max_size(pstr_string)) { n_char = fgetc(fp_stream); if((char)n_char != c_delimiter && n_char != EOF) { string_push_back(pstr_string, (char)n_char); } } if((char)n_char == c_delimiter) { return true; } else { return false; } } }
void err_msg_adding(char* msg, char* sname, int line) { char* tmp = MALLOC(strlen(sname) + 128 + strlen(msg)); snprintf(tmp, strlen(sname) + 128 + strlen(msg), "%s %d: %s\n", sname, line, msg); string_push_back(gErrMsg, tmp); FREE(tmp); }
LIST *property_set_create( PARSE *parse, FRAME *frame ) { LIST* properties = lol_get( frame->args, 0 ); LIST* sorted = 0; LIST* order_sensitive = 0; LIST* unique; LIST* tmp; LIST* val; string var[1]; #if 0 /* Sort all properties which are not order sensitive */ for(tmp = properties; tmp; tmp = tmp->next) { LIST* g = get_grist(tmp->string); LIST* att = call_rule("feature.attributes", frame, g, 0); if (list_in(att, "order-sensitive")) { order_sensitive = list_new( order_sensitive, tmp->string); } else { sorted = list_new( sorted, tmp->string); } list_free(att); } sorted = list_sort(sorted); sorted = list_append(sorted, order_sensitive); unique = list_unique(sorted); #endif sorted = list_sort(properties); unique = list_unique(sorted); string_new(var); string_append(var, ".ps."); for(tmp = unique; tmp; tmp = tmp->next) { string_append(var, tmp->string); string_push_back(var, '-'); } val = var_get(var->value); if (val == 0) { val = call_rule("new", frame, list_append(list_new(0, "property-set"), unique), 0); var_set(newstr(var->value), list_copy(0, val), VAR_SET); } else { val = list_copy(0, val); } string_free(var); /* The 'unique' variable is freed in 'call_rule'. */ list_free(sorted); return val; }
const char * path_tmpfile(void) { const char * result = 0; string file_path; string_copy(&file_path,path_tmpdir()); string_push_back(&file_path,PATH_DELIM); string_append(&file_path,path_tmpnam()); result = newstr(file_path.value); string_free(&file_path); return result; }
void string_unit_test() { { string s[ 1 ]; int i; int const limit = sizeof( s->opt ) * 2 + 2; string_new( s ); assert( s->value == s->opt ); for ( i = 0; i < limit; ++i ) { string_push_back( s, (char)( i + 1 ) ); assert( s->size == i + 1 ); } assert( s->size == limit ); assert( s->value != s->opt ); for ( i = 0; i < limit; ++i ) assert( s->value[ i ] == (char)( i + 1 ) ); string_free( s ); } { char * const original = " \n\t\v Foo \r\n\v \tBar\n\n\r\r\t\n\v\t \t"; string copy[ 1 ]; string_copy( copy, original ); assert( !strcmp( copy->value, original ) ); assert( copy->size == strlen( original ) ); string_free( copy ); } { char * const foo = "Foo "; string foo_copy[ 1 ]; string_copy( foo_copy, foo ); string_rtrim( foo_copy ); assert( !strcmp( foo_copy->value, "Foo" ) ); string_rtrim( foo_copy ); assert( !strcmp( foo_copy->value, "Foo" ) ); } { char * const bar = "Bar\0\0\0"; string bar_copy[ 1 ]; string_copy( bar_copy, bar ); string_rtrim( bar_copy ); assert( !strcmp( bar_copy->value, "Bar" ) ); string_rtrim( bar_copy ); assert( !strcmp( bar_copy->value, "Bar" ) ); } }
/** LyricsWiki parsing strategy: * - start from first hit of "<div class='lyricbox'>" * - search until first html entity * - start converting entities to utf-32 and <br />s to newlines * - if over 48 characters without html entity (allows up to 8 <br />s, for * instance), stop */ static char *parse_lyrics_page(char *page) { char *p; int gap = 0; uint32_t chr; char *tmp; string_t *string, *result; p = strstr(page, "<div class='lyricbox'>"); if (!p) { return NULL; } string = string_new(); for (; *p != '\0'; ++p) { if (string_size(string) > 0 && gap > 48) { break; } ++gap; if (!strncmp(p, "&#", 2)) { if (sscanf(p + 2, "%d;", &chr) < 1) { continue; } gap = 0; tmp = (char *)&chr; string_push_back(string, tmp[0]); string_push_back(string, tmp[1]); string_push_back(string, tmp[2]); string_push_back(string, tmp[3]); } else if (!strncmp(p, "<br />", 6)) { string_push_back(string, '\n'); string_push_back(string, '\0'); string_push_back(string, '\0'); string_push_back(string, '\0'); } } result = string_iconv(string, "UTF-8", "UTF-32"); string_free(string); return string_release(result); }
/** * Read the character string from specific stream. */ void string_input(string_t* pstr_string, FILE* fp_stream) { int n_char = EOF; assert(pstr_string != NULL); assert(fp_stream != NULL); clearerr(fp_stream); string_clear(pstr_string); while (!feof(fp_stream) && !ferror(fp_stream) && string_size(pstr_string) < string_max_size(pstr_string)) { if ((n_char = fgetc(fp_stream)) != EOF) { string_push_back(pstr_string, (char)n_char); } } }
OBJECT * path_tmpfile(void) { OBJECT * result = 0; OBJECT * tmpnam; string file_path; string_copy(&file_path,path_tmpdir()); string_push_back(&file_path,PATH_DELIM); tmpnam = path_tmpnam(); string_append(&file_path,object_str(tmpnam)); object_free(tmpnam); result = object_new(file_path.value); string_free(&file_path); return result; }
void query_filter(query_t *query, query_field_t field, const char *filter) { string_t *string; if (!filter) { query->filters[field] = NULL; return; } if (!id_fields[field]) { query->filters[field] = stringf("%%%s%%", filter); return; } /* The field is an id field. Ensure the filter is a comma-separated list of * decimal numbers. */ string = string_new(); for (; *filter != '\0'; ++filter) { if (*filter == ',' || (*filter >= '0' && *filter <= '9')) { string_push_back(string, *filter); } } query->filters[field] = string_release(string); }
void string_unit_test() { string s[1]; int i; char buffer[sizeof(s->opt) * 2 + 2]; int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer); string_new(s); for (i = 0; i < limit; ++i) { string_push_back( s, (char)(i + 1) ); }; for (i = 0; i < limit; ++i) { assert( i < s->size ); assert( s->value[i] == (char)(i + 1)); } string_free(s); }
void exec_cmd ( char * command, void (* func)( void * closure, int status, timing_info *, char * invoked_command, char * command_output ), void * closure, LIST * shell, char * action, char * target ) { int slot; int raw_cmd = 0 ; char * argv_static[ MAXARGC + 1 ]; /* +1 for NULL */ char * * argv = argv_static; char * p; char * command_orig = command; /* Check to see if we need to hack around the line-length limitation. Look * for a JAMSHELL setting of "%", indicating that the command should be * invoked directly. */ if ( shell && !strcmp( shell->string, "%" ) && !list_next( shell ) ) { raw_cmd = 1; shell = 0; } /* Find a slot in the running commands table for this one. */ for ( slot = 0; slot < MAXJOBS; ++slot ) if ( !cmdtab[ slot ].pi.hProcess ) break; if ( slot == MAXJOBS ) { printf( "no slots for child!\n" ); exit( EXITBAD ); } /* Compute the name of a temp batch file, for possible use. */ if ( !cmdtab[ slot ].tempfile_bat ) { char const * tempdir = path_tmpdir(); DWORD procID = GetCurrentProcessId(); /* SVA - allocate 64 bytes extra just to be safe. */ cmdtab[ slot ].tempfile_bat = BJAM_MALLOC_ATOMIC( strlen( tempdir ) + 64 ); sprintf( cmdtab[ slot ].tempfile_bat, "%s\\jam%d-%02d.bat", tempdir, procID, slot ); } /* Trim leading, -ending- white space */ while ( *( command + 1 ) && isspace( *command ) ) ++command; /* Write to .BAT file unless the line would be too long and it meets the * other spawnability criteria. */ if ( raw_cmd && ( can_spawn( command ) >= MAXLINE ) ) { if ( DEBUG_EXECCMD ) printf("Executing raw command directly\n"); } else { FILE * f = 0; int tries = 0; raw_cmd = 0; /* Write command to bat file. For some reason this open can fail * intermitently. But doing some retries works. Most likely this is due * to a previously existing file of the same name that happens to be * opened by an active virus scanner. Pointed out and fixed by Bronek * Kozicki. */ for ( ; !f && ( tries < 4 ); ++tries ) { f = fopen( cmdtab[ slot ].tempfile_bat, "w" ); if ( !f && ( tries < 4 ) ) Sleep( 250 ); } if ( !f ) { printf( "failed to write command file!\n" ); exit( EXITBAD ); } fputs( command, f ); fclose( f ); command = cmdtab[ slot ].tempfile_bat; if ( DEBUG_EXECCMD ) { if ( shell ) printf( "using user-specified shell: %s", shell->string ); else printf( "Executing through .bat file\n" ); } } /* Formulate argv; If shell was defined, be prepared for % and ! subs. * Otherwise, use stock cmd.exe. */ if ( shell ) { int i; char jobno[ 4 ]; int gotpercent = 0; sprintf( jobno, "%d", slot + 1 ); for ( i = 0; shell && ( i < MAXARGC ); ++i, shell = list_next( shell ) ) { switch ( shell->string[ 0 ] ) { case '%': argv[ i ] = command; ++gotpercent; break; case '!': argv[ i ] = jobno; break; default : argv[ i ] = shell->string; } if ( DEBUG_EXECCMD ) printf( "argv[%d] = '%s'\n", i, argv[ i ] ); } if ( !gotpercent ) argv[ i++ ] = command; argv[ i ] = 0; } else if ( raw_cmd ) { argv = string_to_args( command ); } else { argv[ 0 ] = "cmd.exe"; argv[ 1 ] = "/Q/C"; /* anything more is non-portable */ argv[ 2 ] = command; argv[ 3 ] = 0; } /* Catch interrupts whenever commands are running. */ if ( !cmdsrunning++ ) istat = signal( SIGINT, onintr ); /* Start the command. */ { SECURITY_ATTRIBUTES sa = { sizeof( SECURITY_ATTRIBUTES ), 0, 0 }; SECURITY_DESCRIPTOR sd; STARTUPINFO si = { sizeof( STARTUPINFO ), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; string cmd; /* Init the security data. */ InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION ); SetSecurityDescriptorDacl( &sd, TRUE, NULL, FALSE ); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = TRUE; /* Create the stdout, which is also the merged out + err, pipe. */ if ( !CreatePipe( &cmdtab[ slot ].pipe_out[ 0 ], &cmdtab[ slot ].pipe_out[ 1 ], &sa, 0 ) ) { perror( "CreatePipe" ); exit( EXITBAD ); } /* Create the stdout, which is also the merged out+err, pipe. */ if ( globs.pipe_action == 2 ) { if ( !CreatePipe( &cmdtab[ slot ].pipe_err[ 0 ], &cmdtab[ slot ].pipe_err[ 1 ], &sa, 0 ) ) { perror( "CreatePipe" ); exit( EXITBAD ); } } /* Set handle inheritance off for the pipe ends the parent reads from. */ SetHandleInformation( cmdtab[ slot ].pipe_out[ 0 ], HANDLE_FLAG_INHERIT, 0 ); if ( globs.pipe_action == 2 ) SetHandleInformation( cmdtab[ slot ].pipe_err[ 0 ], HANDLE_FLAG_INHERIT, 0 ); /* Hide the child window, if any. */ si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; /* Set the child outputs to the pipes. */ si.dwFlags |= STARTF_USESTDHANDLES; si.hStdOutput = cmdtab[ slot ].pipe_out[ 1 ]; if ( globs.pipe_action == 2 ) { /* Pipe stderr to the action error output. */ si.hStdError = cmdtab[ slot ].pipe_err[ 1 ]; } else if ( globs.pipe_action == 1 ) { /* Pipe stderr to the console error output. */ si.hStdError = GetStdHandle( STD_ERROR_HANDLE ); } else { /* Pipe stderr to the action merged output. */ si.hStdError = cmdtab[ slot ].pipe_out[ 1 ]; } /* Let the child inherit stdin, as some commands assume it's available. */ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); /* Save the operation for exec_wait() to find. */ cmdtab[ slot ].func = func; cmdtab[ slot ].closure = closure; if ( action && target ) { string_copy( &cmdtab[ slot ].action, action ); string_copy( &cmdtab[ slot ].target, target ); } else { string_free( &cmdtab[ slot ].action ); string_new ( &cmdtab[ slot ].action ); string_free( &cmdtab[ slot ].target ); string_new ( &cmdtab[ slot ].target ); } string_copy( &cmdtab[ slot ].command, command_orig ); /* Put together the command we run. */ { char * * argp = argv; string_new( &cmd ); string_copy( &cmd, *(argp++) ); while ( *argp ) { string_push_back( &cmd, ' ' ); string_append( &cmd, *(argp++) ); } } /* Create output buffers. */ string_new( &cmdtab[ slot ].buffer_out ); string_new( &cmdtab[ slot ].buffer_err ); /* Run the command by creating a sub-process for it. */ if ( ! CreateProcess( NULL , /* application name */ cmd.value , /* command line */ NULL , /* process attributes */ NULL , /* thread attributes */ TRUE , /* inherit handles */ CREATE_NEW_PROCESS_GROUP, /* create flags */ NULL , /* env vars, null inherits env */ NULL , /* current dir, null is our */ /* current dir */ &si , /* startup info */ &cmdtab[ slot ].pi /* child process info, if created */ ) ) { perror( "CreateProcess" ); exit( EXITBAD ); } /* Clean up temporary stuff. */ string_free( &cmd ); } /* Wait until we are under the limit of concurrent commands. Do not trust * globs.jobs alone. */ while ( ( cmdsrunning >= MAXJOBS ) || ( cmdsrunning >= globs.jobs ) ) if ( !exec_wait() ) break; if ( argv != argv_static ) free_argv( argv ); }
int var_string( const char * in, char * out, int outsize, LOL * lol ) { char * out0 = out; char * oute = out + outsize - 1; while ( *in ) { char * lastword; int dollar = 0; /* Copy white space. */ while ( isspace( *in ) ) { if ( out >= oute ) return -1; *out++ = *in++; } lastword = out; /* Copy non-white space, watching for variables. */ while ( *in && !isspace( *in ) ) { if ( out >= oute ) return -1; if ( ( in[ 0 ] == '$' ) && ( in[ 1 ] == '(' ) ) { ++dollar; *out++ = *in++; } #ifdef OPT_AT_FILES else if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) ) { int depth = 1; const char * ine = in + 2; const char * split = 0; /* Scan the content of the response file @() section. */ while ( *ine && ( depth > 0 ) ) { switch ( *ine ) { case '(': ++depth; break; case ')': --depth; break; case ':': if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '=' ) ) split = ine; break; } ++ine; } if ( !split ) { /* the @() reference doesn't match the @(foo:E=bar) format. hence we leave it alone by copying directly to output. */ int l = 0; if ( out + 2 >= oute ) return -1; *( out++ ) = '@'; *( out++ ) = '('; l = var_string( in + 2, out, oute - out, lol ); if ( l < 0 ) return -1; out += l; if ( out + 1 >= oute ) return -1; *( out++ ) = ')'; } else if ( depth == 0 ) { string file_name_v; OBJECT * file_name = 0; int file_name_l = 0; const char * file_name_s = 0; /* Expand the temporary file name var inline. */ #if 0 string_copy( &file_name_v, "$(" ); string_append_range( &file_name_v, in + 2, split ); string_push_back( &file_name_v, ')' ); #else string_new( &file_name_v ); string_append_range( &file_name_v, in + 2, split ); #endif file_name_l = var_string( file_name_v.value, out, oute - out + 1, lol ); string_free( &file_name_v ); if ( file_name_l < 0 ) return -1; file_name_s = out; /* For stdout/stderr we will create a temp file and generate * a command that outputs the content as needed. */ if ( ( strcmp( "STDOUT", out ) == 0 ) || ( strcmp( "STDERR", out ) == 0 ) ) { int err_redir = strcmp( "STDERR", out ) == 0; out[ 0 ] = '\0'; file_name = path_tmpfile(); file_name_s = object_str(file_name); file_name_l = strlen(file_name_s); #ifdef OS_NT if ( ( out + 7 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute ) return -1; sprintf( out,"type \"%s\"%s", file_name_s, err_redir ? " 1>&2" : "" ); #else if ( ( out + 6 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute ) return -1; sprintf( out,"cat \"%s\"%s", file_name_s, err_redir ? " 1>&2" : "" ); #endif /* We also make sure that the temp files created by this * get nuked eventually. */ file_remove_atexit( file_name ); } /* Expand the file value into the file reference. */ var_string_to_file( split + 3, ine - split - 4, file_name_s, lol ); if ( file_name ) { object_free( file_name ); } /* Continue on with the expansion. */ out += strlen( out ); } /* And continue with the parsing just past the @() reference. */ in = ine; } #endif else { *out++ = *in++; } } /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */ if ( out >= oute ) return -1; /* Do not increment, intentionally. */ *out = '\0'; /* If a variable encountered, expand it and and embed the * space-separated members of the list in the output. */ if ( dollar ) { LIST * l = var_expand( L0, lastword, out, lol, 0 ); LIST * saved = l; out = lastword; while ( l ) { int so = strlen( object_str( l->value ) ); if ( out + so >= oute ) return -1; strcpy( out, object_str( l->value ) ); out += so; l = list_next( l ); if ( l ) *out++ = ' '; } list_free( saved ); } } if ( out >= oute ) return -1; *out++ = '\0'; return out - out0; }
void path_build( PATHNAME * f, string * file, int binding ) { struct dirinf root; struct dirinf dir; int g; file_build1( f, file ); /* Get info on root and dir for combining. */ dir_flags( f->f_root.ptr, f->f_root.len, &root ); dir_flags( f->f_dir.ptr, f->f_dir.len, &dir ); /* Combine. */ switch ( g = grid[ root.flags ][ dir.flags ] ) { case G_DIR: /* take dir */ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len ); break; case G_ROOT: /* take root */ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len ); break; case G_VAD: /* root's dev + abs directory */ string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len ); string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len ); break; case G_DRD: case G_DDD: /* root's dev:[dir] + rel directory */ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len ); /* sanity checks: root ends with ] */ if ( file->value[file->size - 1] == ']' ) string_pop_back( file ); /* Add . if separating two -'s */ if ( g == G_DDD ) string_push_back( file, '.' ); /* skip [ of dir */ string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1 ); break; case G_VRD: /* root's dev + rel directory made abs */ string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len ); string_push_back( file, '[' ); /* skip [. of rel dir */ string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2 ); break; } # ifdef DEBUG if ( DEBUG_SEARCH && ( root.flags || dir.flags ) ) printf( "%d x %d = %d (%s)\n", root.flags, dir.flags, grid[ root.flags ][ dir.flags ], file->value ); # endif /* * Now do the special :P modifier when no file was present. * (none) (none) * [dir1.dir2] [dir1] * [dir] [000000] * [.dir] (none) * [] [] */ if ( ( file->value[ file->size - 1 ] == ']' ) && f->parent ) { char * p = file->value + file->size; while ( p-- > file->value ) { if ( *p == '.' ) { /* If we've truncated everything and left with '[', return empty string. */ if ( p == file->value + 1 ) string_truncate( file, 0 ); else { string_truncate( file, p - file->value ); string_push_back( file, ']' ); } break; } if ( *p == '-' ) { /* handle .- or - */ if ( ( p > file->value ) && ( p[ -1 ] == '.' ) ) --p; *p++ = ']'; break; } if ( *p == '[' ) { if ( p[ 1 ] == ']' ) { /* CONSIDER: I don't see any use of this code. We immediately break, and 'p' is a local variable. */ p += 2; } else { string_truncate( file, p - file->value ); string_append( file, "[000000]" ); } break; } } } /* Now copy the file pieces. */ if ( f->f_base.len ) { string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len ); } /* If there is no suffix, we append a "." onto all generated names. This * keeps VMS from appending its own (wrong) idea of what the suffix should * be. */ if ( f->f_suffix.len ) string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len ); else if ( binding && f->f_base.len ) string_push_back( file, '.' ); if ( f->f_member.len ) { string_push_back( file, '(' ); string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len ); string_push_back( file, ')' ); } # ifdef DEBUG if ( DEBUG_SEARCH ) printf( "built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n", f->f_root.len, f->f_root.ptr, f->f_dir.len, f->f_dir.ptr, f->f_base.len, f->f_base.ptr, f->f_suffix.len, f->f_suffix.ptr, f->f_member.len, f->f_member.ptr, file->value ); # endif }
static void canonicWindowsPath( char const * const path, int const path_length, string * const out ) { char const * last_element; unsigned long saved_size; char const * p; /* This is only called via path_key(), which initializes the cache. */ assert( path_key_cache ); if ( !path_length ) return; if ( path_length == 1 && path[ 0 ] == '\\' ) { string_push_back( out, '\\' ); return; } if ( path[ 1 ] == ':' && ( path_length == 2 || ( path_length == 3 && path[ 2 ] == '\\' ) ) ) { string_push_back( out, toupper( path[ 0 ] ) ); string_push_back( out, ':' ); string_push_back( out, '\\' ); return; } /* Find last '\\'. */ for ( p = path + path_length - 1; p >= path && *p != '\\'; --p ); last_element = p + 1; /* Special case '\' && 'D:\' - include trailing '\'. */ if ( p == path || p == path + 2 && path[ 1 ] == ':' ) ++p; if ( p >= path ) { char const * const dir = path; int const dir_length = p - path; OBJECT * const dir_obj = object_new_range( dir, dir_length ); int found; path_key_entry * const result = (path_key_entry *)hash_insert( path_key_cache, dir_obj, &found ); if ( !found ) { result->path = dir_obj; canonicWindowsPath( dir, dir_length, out ); result->key = object_new( out->value ); } else { object_free( dir_obj ); string_append( out, object_str( result->key ) ); } } if ( out->size && out->value[ out->size - 1 ] != '\\' ) string_push_back( out, '\\' ); saved_size = out->size; string_append_range( out, last_element, path + path_length ); { char const * const n = last_element; int const n_length = path + path_length - n; if ( !( n_length == 1 && n[ 0 ] == '.' ) && !( n_length == 2 && n[ 0 ] == '.' && n[ 1 ] == '.' ) ) { WIN32_FIND_DATA fd; HANDLE const hf = FindFirstFileA( out->value, &fd ); if ( hf != INVALID_HANDLE_VALUE ) { string_truncate( out, saved_size ); string_append( out, fd.cFileName ); FindClose( hf ); } } } }
void path_build( PATHNAME *f, string *file, int binding ) { file_build1( f, file ); /* Don't prepend root if it's . or directory is rooted */ # if PATH_DELIM == '/' if ( f->f_root.len && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' ) && !( f->f_dir.len && f->f_dir.ptr[0] == '/' ) ) # else /* unix */ if ( f->f_root.len && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' ) && !( f->f_dir.len && f->f_dir.ptr[0] == '/' ) && !( f->f_dir.len && f->f_dir.ptr[0] == '\\' ) && !( f->f_dir.len && f->f_dir.ptr[1] == ':' ) ) # endif /* unix */ { string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len ); /* If 'root' already ends with path delimeter, don't add yet another one. */ if ( ! is_path_delim( f->f_root.ptr[f->f_root.len-1] ) ) string_push_back( file, as_path_delim( f->f_root.ptr[f->f_root.len] ) ); } if ( f->f_dir.len ) string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len ); /* UNIX: Put / between dir and file */ /* NT: Put \ between dir and file */ if ( f->f_dir.len && ( f->f_base.len || f->f_suffix.len ) ) { /* UNIX: Special case for dir \ : don't add another \ */ /* NT: Special case for dir / : don't add another / */ # if PATH_DELIM == '\\' if ( !( f->f_dir.len == 3 && f->f_dir.ptr[1] == ':' ) ) # endif if ( !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[0] ) ) ) string_push_back( file, as_path_delim( f->f_dir.ptr[f->f_dir.len] ) ); } if ( f->f_base.len ) { string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len ); } if ( f->f_suffix.len ) { string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len ); } if ( f->f_member.len ) { string_push_back( file, '(' ); string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len ); string_push_back( file, ')' ); } }
static void reportWindowsError( char const * const apiName, int slot ) { char * errorMessage; char buf[24]; string * err_buf; timing_info time; DWORD const errorCode = GetLastError(); DWORD apiResult = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | /* __in DWORD dwFlags */ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, /* __in_opt LPCVOID lpSource */ errorCode, /* __in DWORD dwMessageId */ 0, /* __in DWORD dwLanguageId */ (LPSTR)&errorMessage, /* __out LPTSTR lpBuffer */ 0, /* __in DWORD nSize */ 0 ); /* __in_opt va_list * Arguments */ /* Build a message as if the process had written to stderr. */ if ( globs.pipe_action ) err_buf = cmdtab[ slot ].buffer_err; else err_buf = cmdtab[ slot ].buffer_out; string_append( err_buf, apiName ); string_append( err_buf, "() Windows API failed: " ); sprintf( buf, "%d", errorCode ); string_append( err_buf, buf ); if ( !apiResult ) string_append( err_buf, ".\n" ); else { string_append( err_buf, " - " ); string_append( err_buf, errorMessage ); /* Make sure that the buffer is terminated with a newline */ if( err_buf->value[ err_buf->size - 1 ] != '\n' ) string_push_back( err_buf, '\n' ); LocalFree( errorMessage ); } /* Since the process didn't actually start, use a blank timing_info. */ time.system = 0; time.user = 0; timestamp_current( &time.start ); timestamp_current( &time.end ); /* Invoke the callback with a failure status. */ (*cmdtab[ slot ].func)( cmdtab[ slot ].closure, EXEC_CMD_FAIL, &time, cmdtab[ slot ].buffer_out->value, cmdtab[ slot ].buffer_err->value, EXIT_OK ); /* Clean up any handles that were opened. */ closeWinHandle( &cmdtab[ slot ].pi.hProcess ); closeWinHandle( &cmdtab[ slot ].pi.hThread ); closeWinHandle( &cmdtab[ slot ].pipe_out[ EXECCMD_PIPE_READ ] ); closeWinHandle( &cmdtab[ slot ].pipe_out[ EXECCMD_PIPE_WRITE ] ); closeWinHandle( &cmdtab[ slot ].pipe_err[ EXECCMD_PIPE_READ ] ); closeWinHandle( &cmdtab[ slot ].pipe_err[ EXECCMD_PIPE_WRITE ] ); string_renew( cmdtab[ slot ].buffer_out ); string_renew( cmdtab[ slot ].buffer_err ); }
int var_string( char *in, char *out, int outsize, LOL *lol ) { char *out0 = out; char *oute = out + outsize - 1; while( *in ) { char *lastword; int dollar = 0; /* Copy white space */ while( isspace( *in ) ) { if( out >= oute ) return -1; *out++ = *in++; } lastword = out; /* Copy non-white space, watching for variables */ while( *in && !isspace( *in ) ) { if( out >= oute ) return -1; if( in[0] == '$' && in[1] == '(' ) dollar++; #ifdef OPT_AT_FILES else if ( in[0] == '@' && in[1] == '(' ) { int depth = 1; char *ine = in + 2; char *split = 0; /* Scan the content of the response file @() section. */ while( *ine && depth > 0 ) { switch( *ine ) { case '(': ++depth; break; case ')': --depth; break; case ':': if( depth == 1 && ine[1] == 'E' && ine[2] == '=' ) { split = ine; } break; } ++ine; } if (!split) { printf( "no file specified!\n" ); exit( EXITBAD ); } if ( depth == 0 ) { string file_name_v; int file_name_l = 0; const char * file_name_s = 0; /* expand the temporary file name var inline */ #if 0 string_copy(&file_name_v,"$("); string_append_range(&file_name_v,in+2,split); string_push_back(&file_name_v,')'); #else string_new(&file_name_v); string_append_range(&file_name_v,in+2,split); #endif file_name_l = var_string(file_name_v.value,out,oute-out+1,lol); string_free(&file_name_v); if ( file_name_l < 0 ) return -1; file_name_s = out; /* for stdout/stderr we will create a temp file and generate a command that outputs the content as needed. */ if ( strcmp( "STDOUT", out ) == 0 || strcmp( "STDERR", out ) == 0 ) { int err_redir = strcmp( "STDERR", out ) == 0; out[0] = '\0'; file_name_s = path_tmpfile(); file_name_l = strlen(file_name_s); #ifdef OS_NT if ( (out+7+file_name_l+(err_redir?5:0)) >= oute ) return -1; sprintf( out,"type \"%s\"%s", file_name_s, err_redir ? " 1>&2" : "" ); #else if ( (out+6+file_name_l+(err_redir?5:0)) >= oute ) return -1; sprintf( out,"cat \"%s\"%s", file_name_s, err_redir ? " 1>&2" : "" ); #endif /* we also make sure that the temp files created by this get nuked eventually. */ file_remove_atexit( file_name_s ); } /* expand the file value into the file reference */ if ( !globs.noexec ) var_string_to_file( split+3, ine-split-4, file_name_s, lol ); /* continue on with the expansion */ out += strlen(out); } /* and continue with the parsing just past the @() reference */ in = ine; } #endif *out++ = *in++; } /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */ if (out >= oute) return -1; /* Don't increment, intentionally. */ *out= '\0'; /* If a variable encountered, expand it and and embed the */ /* space-separated members of the list in the output. */ if( dollar ) { LIST *l; l = var_expand( L0, lastword, out, lol, 0 ); out = lastword; while ( l ) { int so = strlen( l->string ); if( out + so >= oute ) return -1; strcpy( out, l->string ); out += so; l = list_next( l ); if ( l ) *out++ = ' '; } list_free( l ); } } if( out >= oute ) return -1; *out++ = '\0'; return out - out0; }
void path_build( PATHNAME *f, string* file, int binding ) { int dflag, rflag, act; file_build1( f, file ); /* Combine root & directory, according to the grid. */ dflag = file_flags( f->f_dir.ptr, f->f_dir.len ); rflag = file_flags( f->f_root.ptr, f->f_root.len ); switch( act = grid[ rflag ][ dflag ] ) { case G_DTDR: { /* :: of rel dir */ string_push_back( file, DELIM ); } /* fall through */ case G_DIR: /* take dir */ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len ); break; case G_ROOT: /* take root */ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len ); break; case G_CAT: /* prepend root to dir */ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len ); if( file->value[file->size - 1] == DELIM ) string_pop_back( file ); string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len ); break; case G_DDDD: /* make it ::: (../..) */ string_append( file, ":::" ); break; } /* Put : between dir and file (if none already) */ if( act != G_MT && file->value[file->size - 1] != DELIM && ( f->f_base.len || f->f_suffix.len ) ) { string_push_back( file, DELIM ); } if( f->f_base.len ) { string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len ); } if( f->f_suffix.len ) { string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len ); } if( f->f_member.len ) { string_push_back( file, '(' ); string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len ); string_push_back( file, ')' ); } if( DEBUG_SEARCH ) printf(" -> '%s'\n", file->value); }
void ShortPathToLongPath( char * short_path, string * out ) { const char * new_element; unsigned long saved_size; char * p; if ( short_path[0] == '\0' ) { return; } if ( short_path[0] == '\\' && short_path[1] == '\0') { string_push_back( out, '\\' ); return; } if ( short_path[1] == ':' && ( short_path[2] == '\0' || ( short_path[2] == '\\' && short_path[3] == '\0' ) ) ) { string_push_back( out, toupper( short_path[0] ) ); string_push_back( out, ':' ); string_push_back( out, '\\' ); return; } /* '/' already handled. */ if ( ( p = strrchr( short_path, '\\' ) ) ) { char saved; new_element = p + 1; /* special case \ */ if ( p == short_path ) ++p; /* special case D:\ */ if ( p == short_path + 2 && short_path[1] == ':' ) ++p; saved = *p; *p = '\0'; path_write_key( short_path, out ); *p = saved; } else { new_element = short_path; } if ( out->size && out->value[ out->size - 1 ] != '\\' ) { string_push_back( out, '\\' ); } saved_size = out->size; string_append( out, new_element ); if ( ! ( new_element[0] == '.' && new_element[1] == '\0' || new_element[0] == '.' && new_element[1] == '.' && new_element[2] == '\0' ) ) { WIN32_FIND_DATA fd; HANDLE hf = 0; hf = FindFirstFile( out->value, &fd ); /* If the file exists, replace the name. */ if ( hf != INVALID_HANDLE_VALUE ) { string_truncate( out, saved_size ); string_append( out, fd.cFileName ); FindClose( hf ); } } }