mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Add '+=' append operator to configuration files.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@135717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -199,6 +199,10 @@ Miscellaneous | ||||
|     Skinny channels only. | ||||
|   * You can now compile Asterisk against the Hoard Memory Allocator, see doc/hoard.txt | ||||
|     for more information. | ||||
|   * Config file variables may now be appended to, by using the '+=' append | ||||
|     operator.  This is most helpful when working with long SQL queries in | ||||
|     func_odbc.conf, as the queries no longer need to be specified on a single | ||||
|     line. | ||||
|  | ||||
| ------------------------------------------------------------------------------ | ||||
| --- Functionality changes from Asterisk 1.4.X to Asterisk 1.6.0  ------------- | ||||
|   | ||||
| @@ -226,6 +226,13 @@ Configuration: | ||||
| * queues.conf: the queue-lessthan sound file option is no longer available, and the | ||||
|   queue-round-seconds option no longer takes '1' as a valid parameter. | ||||
|  | ||||
| * If you have any third party modules which use a config file variable whose | ||||
|   name ends in a '+', please note that the append capability added to this | ||||
|   version may now conflict with that variable naming scheme.  An easy | ||||
|   workaround is to ensure that a space occurs between the '+' and the '=', | ||||
|   to differentiate your variable from the append operator.  This potential | ||||
|   conflict is unlikely, but is documented here to be thorough. | ||||
|  | ||||
| Manager: | ||||
|  | ||||
| * Manager has been upgraded to version 1.1 with a lot of changes.  | ||||
|   | ||||
| @@ -339,6 +339,15 @@ void ast_include_rename(struct ast_config *conf, const char *from_file, const ch | ||||
| void ast_variable_append(struct ast_category *category, struct ast_variable *variable); | ||||
| void ast_variable_insert(struct ast_category *category, struct ast_variable *variable, const char *line); | ||||
| int ast_variable_delete(struct ast_category *category, const char *variable, const char *match, const char *line); | ||||
|  | ||||
| /*! \brief Update variable value within a config | ||||
|  * \param category Category element within the config | ||||
|  * \param variable Name of the variable to change | ||||
|  * \param value New value of the variable | ||||
|  * \param match If set, previous value of the variable (if NULL or zero-length, no matching will be done) | ||||
|  * \param object Boolean of whether to make the new variable an object | ||||
|  * \return 0 on success or -1 on failure. | ||||
|  */ | ||||
| int ast_variable_update(struct ast_category *category, const char *variable,  | ||||
| 						const char *value, const char *match, unsigned int object); | ||||
|  | ||||
|   | ||||
							
								
								
									
										130
									
								
								main/config.c
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								main/config.c
									
									
									
									
									
								
							| @@ -98,6 +98,14 @@ struct cache_file_mtime { | ||||
|  | ||||
| static AST_LIST_HEAD_STATIC(cfmtime_head, cache_file_mtime); | ||||
|  | ||||
| static int init_appendbuf(void *data) | ||||
| { | ||||
| 	struct ast_str **str = data; | ||||
| 	*str = ast_str_create(16); | ||||
| 	return *str ? 0 : -1; | ||||
| } | ||||
|  | ||||
| AST_THREADSTORAGE_CUSTOM(appendbuf, init_appendbuf, ast_free_ptr); | ||||
|  | ||||
| /* comment buffers are better implemented using the ast_str_*() API */ | ||||
| #define CB_SIZE 250	/* initial size of comment buffers */ | ||||
| @@ -752,12 +760,8 @@ int ast_variable_update(struct ast_category *category, const char *variable, | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (prev) | ||||
| 		prev->next = newer; | ||||
| 	else | ||||
| 		category->root = newer; | ||||
|  | ||||
| 	return 0; | ||||
| 	/* Could not find variable to update */ | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| int ast_category_delete(struct ast_config *cfg, const char *category) | ||||
| @@ -1041,65 +1045,93 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, | ||||
| 			return 0;	/* XXX is this correct ? or we should return -1 ? */ | ||||
| 		} | ||||
|  | ||||
| 				/* Strip off leading and trailing "'s and <>'s */ | ||||
| 				while ((*c == '<') || (*c == '>') || (*c == '\"')) c++; | ||||
| 				/* Get rid of leading mess */ | ||||
| 				cur = c; | ||||
| 				cur2 = cur; | ||||
| 				while (!ast_strlen_zero(cur)) { | ||||
| 					c = cur + strlen(cur) - 1; | ||||
| 					if ((*c == '>') || (*c == '<') || (*c == '\"')) | ||||
| 						*c = '\0'; | ||||
| 					else | ||||
| 						break; | ||||
| 				} | ||||
| 				/* #exec </path/to/executable> | ||||
| 				   We create a tmp file, then we #include it, then we delete it. */ | ||||
| 				if (!do_include) { | ||||
| 					struct timeval tv = ast_tvnow(); | ||||
| 					if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) | ||||
| 						config_cache_attribute(configfile, ATTRIBUTE_EXEC, NULL, who_asked); | ||||
| 					snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d%d.%ld", (int)tv.tv_sec, (int)tv.tv_usec, (long)pthread_self()); | ||||
| 					snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file); | ||||
| 					ast_safe_system(cmd); | ||||
| 					cur = exec_file; | ||||
| 				} else { | ||||
| 					if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) | ||||
| 						config_cache_attribute(configfile, ATTRIBUTE_INCLUDE, cur, who_asked); | ||||
| 					exec_file[0] = '\0'; | ||||
| 				} | ||||
| 				/* A #include */ | ||||
| 				/* record this inclusion */ | ||||
| 				inclu = ast_include_new(cfg, configfile, cur, !do_include, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name)); | ||||
| 		/* Strip off leading and trailing "'s and <>'s */ | ||||
| 		while ((*c == '<') || (*c == '>') || (*c == '\"')) c++; | ||||
| 		/* Get rid of leading mess */ | ||||
| 		cur = c; | ||||
| 		cur2 = cur; | ||||
| 		while (!ast_strlen_zero(cur)) { | ||||
| 			c = cur + strlen(cur) - 1; | ||||
| 			if ((*c == '>') || (*c == '<') || (*c == '\"')) | ||||
| 				*c = '\0'; | ||||
| 			else | ||||
| 				break; | ||||
| 		} | ||||
| 		/* #exec </path/to/executable> | ||||
| 		   We create a tmp file, then we #include it, then we delete it. */ | ||||
| 		if (!do_include) { | ||||
| 			struct timeval tv = ast_tvnow(); | ||||
| 			if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) | ||||
| 				config_cache_attribute(configfile, ATTRIBUTE_EXEC, NULL, who_asked); | ||||
| 			snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d%d.%ld", (int)tv.tv_sec, (int)tv.tv_usec, (long)pthread_self()); | ||||
| 			snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file); | ||||
| 			ast_safe_system(cmd); | ||||
| 			cur = exec_file; | ||||
| 		} else { | ||||
| 			if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) | ||||
| 				config_cache_attribute(configfile, ATTRIBUTE_INCLUDE, cur, who_asked); | ||||
| 			exec_file[0] = '\0'; | ||||
| 		} | ||||
| 		/* A #include */ | ||||
| 		/* record this inclusion */ | ||||
| 		inclu = ast_include_new(cfg, configfile, cur, !do_include, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name)); | ||||
|  | ||||
| 				do_include = ast_config_internal_load(cur, cfg, flags, real_inclusion_name, who_asked) ? 1 : 0; | ||||
| 				if (!ast_strlen_zero(exec_file)) | ||||
| 					unlink(exec_file); | ||||
| 				if (!do_include) { | ||||
| 					ast_log(LOG_ERROR, "The file '%s' was listed as a #include but it does not exist.\n", cur); | ||||
| 					return -1; | ||||
| 				} | ||||
| 				/* XXX otherwise what ? the default return is 0 anyways */ | ||||
| 		do_include = ast_config_internal_load(cur, cfg, flags, real_inclusion_name, who_asked) ? 1 : 0; | ||||
| 		if (!ast_strlen_zero(exec_file)) | ||||
| 			unlink(exec_file); | ||||
| 		if (!do_include) { | ||||
| 			ast_log(LOG_ERROR, "The file '%s' was listed as a #include but it does not exist.\n", cur); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		/* XXX otherwise what ? the default return is 0 anyways */ | ||||
|  | ||||
| 	} else { | ||||
| 		/* Just a line (variable = value) */ | ||||
| 		int object = 0; | ||||
| 		if (!(*cat)) { | ||||
| 			ast_log(LOG_WARNING, | ||||
| 				"parse error: No category context for line %d of %s\n", lineno, configfile); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		c = strchr(cur, '='); | ||||
| 		if (c) { | ||||
| 			int object; | ||||
|  | ||||
| 		if (c && c > cur && (*(c - 1) == '+')) { | ||||
| 			struct ast_variable *var, *replace = NULL; | ||||
| 			struct ast_str **str = ast_threadstorage_get(&appendbuf, sizeof(*str)); | ||||
|  | ||||
| 			if (!str || !*str) { | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			*(c - 1) = '\0'; | ||||
| 			c++; | ||||
| 			cur = ast_strip(cur); | ||||
|  | ||||
| 			/* Must iterate through category until we find last variable of same name (since there could be multiple) */ | ||||
| 			for (var = ast_category_first(*cat); var; var = var->next) { | ||||
| 				if (!strcmp(var->name, cur)) { | ||||
| 					replace = var; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (!replace) { | ||||
| 				/* Nothing to replace; just set a variable normally. */ | ||||
| 				goto set_new_variable; | ||||
| 			} | ||||
|  | ||||
| 			ast_str_set(str, 0, "%s", replace->value); | ||||
| 			ast_str_append(str, 0, "%s", c); | ||||
| 			ast_variable_update(*cat, replace->name, ast_strip((*str)->str), replace->value, object); | ||||
| 		} else if (c) { | ||||
| 			*c = 0; | ||||
| 			c++; | ||||
| 			/* Ignore > in => */ | ||||
| 			if (*c== '>') { | ||||
| 				object = 1; | ||||
| 				c++; | ||||
| 			} else | ||||
| 				object = 0; | ||||
| 			if ((v = ast_variable_new(ast_strip(cur), ast_strip(c), *suggested_include_file ? suggested_include_file : configfile))) { | ||||
| 			} | ||||
| set_new_variable: | ||||
| 			if ((v = ast_variable_new(ast_strip(cur), ast_strip(c), S_OR(suggested_include_file, configfile)))) { | ||||
| 				v->lineno = lineno; | ||||
| 				v->object = object; | ||||
| 				*last_cat = 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user