Sat Mar 24 22:55:17 2007

Asterisk developer's documentation


func_array.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2005, Tilghman Lesher.
00005  *
00006  * See http://www.asterisk.org for more information about
00007  * the Asterisk project. Please do not directly contact
00008  * any of the maintainers of this project for assistance;
00009  * the project provides a web site, mailing lists and IRC
00010  * channels for your use.
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License Version 2. See the LICENSE file
00014  * at the top of the source tree.
00015  */
00016 
00017 /*! \file
00018  *
00019  * \brief ARRAY dialplan function
00020  *
00021  * \author Tilghman Lesher
00022  */
00023 
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include <sys/types.h>
00028 #include <sched.h>
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 20003 $")
00033 
00034 #include "asterisk/module.h"
00035 #include "asterisk/channel.h"
00036 #include "asterisk/pbx.h"
00037 #include "asterisk/logger.h"
00038 #include "asterisk/utils.h"
00039 #include "asterisk/app.h"
00040 #include "asterisk/localtime.h"
00041 
00042 AST_MUTEX_DEFINE_STATIC(local_lock);
00043 static int use_count = 0;
00044 
00045 static unsigned int trunk_app_separate_args(char *buf, char delim, char **array, int arraylen)
00046 {
00047    int argc;
00048    char *scan;
00049    int paren = 0, quote = 0;
00050 
00051    if (!buf || !array || !arraylen)
00052       return 0;
00053 
00054    memset(array, 0, arraylen * sizeof(*array));
00055 
00056    scan = buf;
00057 
00058    for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
00059       array[argc] = scan;
00060       for (; *scan; scan++) {
00061          if (*scan == '(')
00062             paren++;
00063          else if (*scan == ')') {
00064             if (paren)
00065                paren--;
00066          } else if (*scan == '"') {
00067             quote = quote ? 0 : 1;
00068             /* Remove quote character from argument */
00069             memmove(scan, scan + 1, strlen(scan));
00070             scan--;
00071          } else if (*scan == '\\') {
00072             /* Literal character, don't parse */
00073             memmove(scan, scan + 1, strlen(scan));
00074          } else if ((*scan == delim) && !paren && !quote) {
00075             *scan++ = '\0';
00076             break;
00077          }
00078       }
00079    }
00080 
00081    if (*scan)
00082       array[argc++] = scan;
00083 
00084    return argc;
00085 }
00086 
00087 static void array(struct ast_channel *chan, char *cmd, char *var, const char *value)
00088 {
00089    AST_DECLARE_APP_ARGS(arg1,
00090               AST_APP_ARG(var)[100];
00091    );
00092    AST_DECLARE_APP_ARGS(arg2,
00093               AST_APP_ARG(val)[100];
00094    );
00095    char *value2;
00096    int i;
00097 
00098    value2 = ast_strdupa(value);
00099    if (!var || !value2)
00100       return;
00101 
00102    ast_mutex_lock(&local_lock);
00103    use_count++;
00104    ast_mutex_unlock(&local_lock);
00105 
00106    /* The functions this will generally be used with are SORT and ODBC_*, which
00107     * both return comma-delimited lists.  However, if somebody uses literal lists,
00108     * their commas will be translated to vertical bars by the load, and I don't
00109     * want them to be surprised by the result.  Hence, we prefer commas as the
00110     * delimiter, but we'll fall back to vertical bars if commas aren't found.
00111     */
00112    ast_log(LOG_DEBUG, "array (%s=%s)\n", var, value2);
00113    if (strchr(var, ','))
00114       arg1.argc = trunk_app_separate_args(var, ',', arg1.argv, (sizeof(arg1) - sizeof(arg1.argc)) / sizeof(arg1.argv[0]));
00115    else
00116       arg1.argc = trunk_app_separate_args(var, '|', arg1.argv, (sizeof(arg1) - sizeof(arg1.argc)) / sizeof(arg1.argv[0]));
00117 
00118    if (strchr(value2, ','))
00119       arg2.argc = trunk_app_separate_args(value2, ',', arg2.argv, (sizeof(arg2) - sizeof(arg2.argc)) / sizeof(arg2.argv[0]));
00120    else
00121       arg2.argc = trunk_app_separate_args(value2, '|', arg2.argv, (sizeof(arg2) - sizeof(arg2.argc)) / sizeof(arg2.argv[0]));
00122 
00123    for (i = 0; i < arg1.argc; i++) {
00124       ast_log(LOG_DEBUG, "array set value (%s=%s)\n", arg1.var[i],
00125          arg2.val[i]);
00126       if (i < arg2.argc) {
00127          pbx_builtin_setvar_helper(chan, arg1.var[i], arg2.val[i]);
00128       } else {
00129          /* We could unset the variable, by passing a NULL, but due to
00130           * pushvar semantics, that could create some undesired behavior. */
00131          pbx_builtin_setvar_helper(chan, arg1.var[i], "");
00132       }
00133    }
00134 
00135    ast_mutex_lock(&local_lock);
00136    use_count--;
00137    ast_mutex_unlock(&local_lock);
00138 
00139    return;
00140 }
00141 
00142 static struct ast_custom_function array_function = {
00143    .name = "ARRAY",
00144    .synopsis = "Allows setting multiple variables at once",
00145    .syntax = "ARRAY(var1[,var2[...][,varN]])",
00146    .write = array,
00147    .desc =
00148       "The comma-separated list passed as a value to which the function is set will\n"
00149       "be interpreted as a set of values to which the comma-separated list of\n"
00150       "variable names in the argument should be set.\n"
00151       "Hence, Set(ARRAY(var1,var2)=1,2) will set var1 to 1 and var2 to 2\n"
00152       "Note: remember to either backslash your commas in extensions.conf or quote the\n"
00153       "entire argument, since Set can take multiple arguments itself.\n",
00154 };
00155 
00156 static char *tdesc = "String handling dialplan functions";
00157 
00158 int unload_module(void)
00159 {
00160    int res = 0;
00161 
00162    res |= ast_custom_function_unregister(&array_function);
00163    sched_yield(); /* Any remaining process gets time to clear out.  Increases safety if a force unload is attempted. */
00164 
00165    return res;
00166 }
00167 
00168 int load_module(void)
00169 {
00170    int res = 0;
00171 
00172    res |= ast_custom_function_register(&array_function);
00173 
00174    return res;
00175 }
00176 
00177 char *description(void)
00178 {
00179    return tdesc;
00180 }
00181 
00182 int usecount(void)
00183 {
00184    return use_count;
00185 }
00186 
00187 char *key(void)
00188 {
00189    return ASTERISK_GPL_KEY;
00190 }
00191 

Generated on Sat Mar 24 22:55:17 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.7