char * util_alloc_envvar( const char * value ) { if (value == NULL) return NULL; else { buffer_type * buffer = buffer_alloc( 1024 ); /* Start by filling up a buffer instance with the current content of @value. */ buffer_fwrite_char_ptr( buffer , value ); buffer_fwrite_char( buffer , '\0' ); buffer_rewind( buffer ); while (true) { if (buffer_strchr( buffer , '$')) { const char * data = buffer_get_data( buffer ); int offset = buffer_get_offset( buffer ) + 1; /* Points at the first character following the '$' */ int var_length = 0; /* Find the length of the variable name */ while (true) { char c; c = data[offset + var_length]; if (!(isalnum( c ) || c == '_')) /* Any character which is NOT in the set [a-Z,0-9_] marks the end of the variable. */ break; if (c == '\0') /* The end of the string. */ break; var_length += 1; } { char * var_name = util_alloc_substring_copy( data , offset - 1 , var_length + 1); /* Include the leading $ */ const char * var_value = getenv( &var_name[1] ); if (var_value != NULL) buffer_search_replace( buffer , var_name , var_value); /* The actual string replacement. */ else buffer_fseek( buffer , var_length , SEEK_CUR ); /* The variable is not defined, and we leave the $name. */ free( var_name ); } } else break; /* No more $ to replace */ } buffer_shrink_to_fit( buffer ); { char * expanded_value = buffer_get_data( buffer ); buffer_free_container( buffer ); return expanded_value; } } }
/** Updates the buffer inplace with all the string substitutions in the subst_list. This is the lowest level function, which does *NOT* consider the parent pointer. */ static void subst_list_replace_strings__(const subst_list_type * subst_list , buffer_type * buffer) { int index; for (index = 0; index < vector_get_size( subst_list->string_data ); index++) { const subst_list_string_type * node = vector_iget_const( subst_list->string_data , index ); if (node->value != NULL) { bool match; buffer_rewind( buffer ); do { match = buffer_search_replace( buffer , node->key , node->value); } while (match); } } }