Merged revisions 50562 via svnmerge from
[asterisk/asterisk.git] / main / pbx.c
index b13c6f0..10c9911 100644 (file)
@@ -193,7 +193,9 @@ struct ast_state_cb {
 /*! \brief Structure for dial plan hints
 
   \note Hints are pointers from an extension in the dialplan to one or
-  more devices (tech/name) */
+  more devices (tech/name) 
+       - See \ref AstExtState
+*/
 struct ast_hint {
        struct ast_exten *exten;        /*!< Extension */
        int laststate;                  /*!< Last known state */
@@ -238,13 +240,13 @@ static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
 int pbx_builtin_setvar(struct ast_channel *, void *);
 static int pbx_builtin_importvar(struct ast_channel *, void *);
 
-AST_MUTEX_DEFINE_STATIC(globalslock);
+AST_RWLOCK_DEFINE_STATIC(globalslock);
 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
 
 static int autofallthrough = 1;
 
 AST_MUTEX_DEFINE_STATIC(maxcalllock);
-static int countcalls = 0;
+static int countcalls;
 
 static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function);
 
@@ -263,7 +265,8 @@ static struct pbx_builtin {
        "Answer a channel if ringing",
        "  Answer([delay]): If the call has not been answered, this application will\n"
        "answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
-       "Asterisk will wait this number of milliseconds before answering the call.\n"
+       "Asterisk will wait this number of milliseconds before returning to\n"
+       "the dialplan after answering the call.\n"
        },
 
        { "BackGround", pbx_builtin_background,
@@ -458,12 +461,12 @@ static struct pbx_builtin {
 
 };
 
-static struct ast_context *contexts = NULL;
+static struct ast_context *contexts;
 AST_MUTEX_DEFINE_STATIC(conlock);              /*!< Lock for the ast_context list */
 
 static AST_RWLIST_HEAD_STATIC(apps, ast_app);
 
-static AST_LIST_HEAD_STATIC(switches, ast_switch);
+static AST_RWLIST_HEAD_STATIC(switches, ast_switch);
 
 static int stateid = 1;
 /* WARNING:
@@ -473,14 +476,14 @@ static int stateid = 1;
    paths that require both locks must also take them in that order.
 */
 static AST_RWLIST_HEAD_STATIC(hints, ast_hint);
-struct ast_state_cb *statecbs = NULL;
+struct ast_state_cb *statecbs;
 
 /*
    \note This function is special. It saves the stack so that no matter
    how many times it is called, it returns to the same place */
 int pbx_exec(struct ast_channel *c,            /*!< Channel */
-               struct ast_app *app,            /*!< Application */
-               void *data)                     /*!< Data for execution */
+            struct ast_app *app,               /*!< Application */
+            void *data)                        /*!< Data for execution */
 {
        int res;
 
@@ -534,12 +537,12 @@ static struct ast_switch *pbx_findswitch(const char *sw)
 {
        struct ast_switch *asw;
 
-       AST_LIST_LOCK(&switches);
-       AST_LIST_TRAVERSE(&switches, asw, list) {
+       AST_RWLIST_RDLOCK(&switches);
+       AST_RWLIST_TRAVERSE(&switches, asw, list) {
                if (!strcasecmp(asw->name, sw))
                        break;
        }
-       AST_LIST_UNLOCK(&switches);
+       AST_RWLIST_UNLOCK(&switches);
 
        return asw;
 }
@@ -1094,9 +1097,12 @@ static char *substring(const char *value, int offset, int length, char *workspac
        return ret;
 }
 
-/*! \brief  pbx_retrieve_variable: Support for Asterisk built-in variables and
-      functions in the dialplan
-  ---*/
+/*! \brief  Support for Asterisk built-in variables and functions in the dialplan
+
+\note  See also
+       - \ref AstVar   Channel variables
+       - \ref AstCauses The HANGUPCAUSE variable
+ */
 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 {
        const char not_found = '\0';
@@ -1185,7 +1191,7 @@ void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, c
                if (!places[i])
                        continue;
                if (places[i] == &globals)
-                       ast_mutex_lock(&globalslock);
+                       ast_rwlock_rdlock(&globalslock);
                AST_LIST_TRAVERSE(places[i], variables, entries) {
                        if (strcasecmp(ast_var_name(variables), var)==0) {
                                s = ast_var_value(variables);
@@ -1193,7 +1199,7 @@ void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, c
                        }
                }
                if (places[i] == &globals)
-                       ast_mutex_unlock(&globalslock);
+                       ast_rwlock_unlock(&globalslock);
        }
        if (s == &not_found || s == NULL)
                *ret = NULL;
@@ -1402,10 +1408,11 @@ static char *func_args(char *function)
        return args;
 }
 
-int ast_func_read(struct ast_channel *chan, char *function, char *workspace, size_t len)
+int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
 {
-       char *args = func_args(function);
-       struct ast_custom_function *acfptr = ast_custom_function_find(function);
+       char *copy = ast_strdupa(function);
+       char *args = func_args(copy);
+       struct ast_custom_function *acfptr = ast_custom_function_find(copy);
 
        if (acfptr == NULL)
                ast_log(LOG_ERROR, "Function %s not registered\n", function);
@@ -1416,10 +1423,11 @@ int ast_func_read(struct ast_channel *chan, char *function, char *workspace, siz
        return -1;
 }
 
-int ast_func_write(struct ast_channel *chan, char *function, const char *value)
+int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
 {
-       char *args = func_args(function);
-       struct ast_custom_function *acfptr = ast_custom_function_find(function);
+       char *copy = ast_strdupa(function);
+       char *args = func_args(copy);
+       struct ast_custom_function *acfptr = ast_custom_function_find(copy);
 
        if (acfptr == NULL)
                ast_log(LOG_ERROR, "Function %s not registered\n", function);
@@ -1624,7 +1632,7 @@ static void pbx_substitute_variables(char *passdata, int datalen, struct ast_cha
        memset(passdata, 0, datalen);
 
        /* No variables or expressions in e->data, so why scan it? */
-       if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
+       if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
                ast_copy_string(passdata, e->data, datalen);
                return;
        }
@@ -2090,7 +2098,6 @@ static int ast_remove_hint(struct ast_exten *e)
        if (!e)
                return -1;
 
-       AST_RWLIST_WRLOCK(&hints);
        AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
                if (hint->exten == e) {
                        cbprev = NULL;
@@ -2110,7 +2117,6 @@ static int ast_remove_hint(struct ast_exten *e)
                }
        }
        AST_RWLIST_TRAVERSE_SAFE_END
-       AST_RWLIST_UNLOCK(&hints);
 
        return res;
 }
@@ -2862,50 +2868,50 @@ int ast_register_switch(struct ast_switch *sw)
 {
        struct ast_switch *tmp;
 
-       AST_LIST_LOCK(&switches);
-       AST_LIST_TRAVERSE(&switches, tmp, list) {
+       AST_RWLIST_WRLOCK(&switches);
+       AST_RWLIST_TRAVERSE(&switches, tmp, list) {
                if (!strcasecmp(tmp->name, sw->name)) {
-                       AST_LIST_UNLOCK(&switches);
+                       AST_RWLIST_UNLOCK(&switches);
                        ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
                        return -1;
                }
        }
-       AST_LIST_INSERT_TAIL(&switches, sw, list);
-       AST_LIST_UNLOCK(&switches);
+       AST_RWLIST_INSERT_TAIL(&switches, sw, list);
+       AST_RWLIST_UNLOCK(&switches);
 
        return 0;
 }
 
 void ast_unregister_switch(struct ast_switch *sw)
 {
-       AST_LIST_LOCK(&switches);
-       AST_LIST_REMOVE(&switches, sw, list);
-       AST_LIST_UNLOCK(&switches);
+       AST_RWLIST_WRLOCK(&switches);
+       AST_RWLIST_REMOVE(&switches, sw, list);
+       AST_RWLIST_UNLOCK(&switches);
 }
 
 /*
  * Help for CLI commands ...
  */
 static char show_applications_help[] =
-"Usage: core list applications [{like|describing} <text>]\n"
+"Usage: core show applications [{like|describing} <text>]\n"
 "       List applications which are currently available.\n"
 "       If 'like', <text> will be a substring of the app name\n"
 "       If 'describing', <text> will be a substring of the description\n";
 
 static char show_functions_help[] =
-"Usage: core list functions [like <text>]\n"
+"Usage: core show functions [like <text>]\n"
 "       List builtin functions, optionally only those matching a given string\n";
 
 static char show_switches_help[] =
-"Usage: core list switches\n"
+"Usage: core show switches\n"
 "       List registered switches\n";
 
 static char show_hints_help[] =
-"Usage: core list hints\n"
+"Usage: core show hints\n"
 "       List registered hints\n";
 
 static char show_globals_help[] =
-"Usage: core list globals\n"
+"Usage: core show globals\n"
 "       List current global dialplan variables and their values\n";
 
 static char show_application_help[] =
@@ -2917,7 +2923,7 @@ static char show_function_help[] =
 "       Describe a particular dialplan function.\n";
 
 static char show_dialplan_help[] =
-"Usage: dialplan show [exten@][context]\n"
+"Usage: core show dialplan [exten@][context]\n"
 "       Show dialplan\n";
 
 static char set_global_help[] =
@@ -3062,19 +3068,19 @@ static int handle_show_switches(int fd, int argc, char *argv[])
 {
        struct ast_switch *sw;
 
-       AST_LIST_LOCK(&switches);
+       AST_RWLIST_RDLOCK(&switches);
 
-       if (AST_LIST_EMPTY(&switches)) {
-               AST_LIST_UNLOCK(&switches);
+       if (AST_RWLIST_EMPTY(&switches)) {
+               AST_RWLIST_UNLOCK(&switches);
                ast_cli(fd, "There are no registered alternative switches\n");
                return RESULT_SUCCESS;
        }
 
        ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
-       AST_LIST_TRAVERSE(&switches, sw, list)
+       AST_RWLIST_TRAVERSE(&switches, sw, list)
                ast_cli(fd, "%s: %s\n", sw->name, sw->description);
 
-       AST_LIST_UNLOCK(&switches);
+       AST_RWLIST_UNLOCK(&switches);
 
        return RESULT_SUCCESS;
 }
@@ -3272,7 +3278,10 @@ static int show_dialplan_helper(int fd, const char *context, const char *exten,
                        dpc->total_prio++;
 
                        /* write extension name and first peer */
-                       snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
+                       if (e->matchcid)
+                               snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
+                       else
+                               snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
 
                        print_ext(e, buf2, sizeof(buf2));
 
@@ -3416,21 +3425,22 @@ static int handle_show_dialplan(int fd, int argc, char *argv[])
 }
 
 /*! \brief Send ack once */
-static void manager_dpsendack(struct mansession *s, struct message *m, int *sentack)
+static void manager_dpsendack(struct mansession *s, const struct message *m)
 {
-       if (*sentack)
-               return;
        astman_send_listack(s, m, "DialPlan list will follow", "start");
-       *sentack = 1;
-       return;
 }
 
-/*! \brief Show dialplan extensions */
-static int manager_show_dialplan_helper(struct mansession *s, struct message *m, char *actionidtext, char *context, char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
+/*! \brief Show dialplan extensions
+ * XXX this function is similar but not exactly the same as the CLI's
+ * show dialplan. Must check whether the difference is intentional or not.
+ */
+static int manager_show_dialplan_helper(struct mansession *s, const struct message *m,
+                                       const char *actionidtext, const char *context,
+                                       const char *exten, struct dialplan_counters *dpc,
+                                       struct ast_include *rinclude)
 {
        struct ast_context *c;
        int res=0, old_total_exten = dpc->total_exten;
-       int sentpositivemanagerack = 0;
 
        if (ast_strlen_zero(exten))
                exten = NULL;
@@ -3447,137 +3457,115 @@ static int manager_show_dialplan_helper(struct mansession *s, struct message *m,
                return -1;
        }
 
-       /* walk all contexts ... */
-       for (c = ast_walk_contexts(NULL); c ; c = ast_walk_contexts(c)) {
-               /* show this context? */
-               if (!context ||
-                       !strcmp(ast_get_context_name(c), context)) {
-                       dpc->context_existence = 1;
+       c = NULL;               /* walk all contexts ... */
+       while ( (c = ast_walk_contexts(c)) ) {
+               struct ast_exten *e;
+               struct ast_include *i;
+               struct ast_ignorepat *ip;
+
+               if (context && strcmp(ast_get_context_name(c), context) != 0)
+                       continue;       /* not the name we want */
+
+               dpc->context_existence = 1;
 
+               if (option_debug > 2)
+                       ast_log(LOG_DEBUG, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
+
+               if (ast_lock_context(c)) {      /* failed to lock */
                        if (option_debug > 2)
-                               ast_log(LOG_DEBUG, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
-
-                       /* try to lock context before walking in ... */
-                       if (!ast_lock_context(c)) {
-                               struct ast_exten *e;
-                               struct ast_include *i;
-                               struct ast_ignorepat *ip;
-                               struct ast_sw *sw;
-                               char buf[256], buf2[256];
-
-                               /* walk extensions in context  */
-                               for (e = ast_walk_context_extensions(c, NULL); e; e = ast_walk_context_extensions(c, e)) {
-                                       struct ast_exten *p;
-                                       int prio;
-
-                                       /* looking for extension? is this our extension? */
-                                       if (exten &&
-                                               !ast_extension_match(ast_get_extension_name(e), exten))
-                                       {
-                                               if (option_debug > 2)
-                                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
-                                               /* we are looking for extension and it's not our
-                                                * extension, so skip to next extension */
-                                               continue;
-                                       }
-                                       if (option_debug > 2)
-                                               ast_log(LOG_DEBUG, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
-
-                                       dpc->extension_existence = 1;
-
-                                       /* may we print context info? */        
-                                       dpc->total_context++;
-                                       dpc->total_prio++;
-
-                                       /* write extension name and first peer */       
-                                       bzero(buf, sizeof(buf));                
-                               
-                                       dpc->total_items++;
-                                       manager_dpsendack(s, m, &sentpositivemanagerack);
-                                       astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
-                                       astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
-
-                                       prio = ast_get_extension_priority(e);
-                                       if (prio == PRIORITY_HINT) {
-                                               astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(e));
-                                       } else {
-                                               astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(e), (char *) ast_get_extension_app_data(e));
-                                       }
-                                       astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
-
-                                       dpc->total_exten++;
-
-                                       /* walk next extension peers */
-                                       for (p=ast_walk_extension_priorities(e, e); p; p=ast_walk_extension_priorities(e, p)) {
-                                               dpc->total_prio++;
-                                               bzero((void *)buf2, sizeof(buf2));
-                                               bzero((void *)buf, sizeof(buf));
-                                               dpc->total_items++;
-                                               manager_dpsendack(s, m, &sentpositivemanagerack);
-                                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
-                                               astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
-
-                                               if (ast_get_extension_label(p))
-                                                       astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
-                                               prio = ast_get_extension_priority(p);
-                                               if (prio == PRIORITY_HINT) {
-                                                       astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
-                                               } else {
-                                                       astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
-                                               }
-                                               astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
-                                       }
-                               }
+                               ast_log(LOG_DEBUG, "manager_show_dialplan: Failed to lock context\n");
+                       continue;
+               }
 
-                               /* walk included and write info ... */
-                               for (i = ast_walk_context_includes(c, NULL); i; i = ast_walk_context_includes(c, i)) {
-                                       if (exten) {
-                                               /* Check all includes for the requested extension */
-                                               manager_show_dialplan_helper(s, m, actionidtext, (char *)ast_get_include_name(i), exten, dpc, i);
-                                       } else {
-                                               dpc->total_items++;
-                                               manager_dpsendack(s, m, &sentpositivemanagerack);
-                                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
-                                               astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
-                                               astman_append(s, "\r\n");
-                                               if (option_debug > 2)
-                                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Found Included context: %s \n", buf);
-                                       }
-                               }
+               /* XXX note- an empty context is not printed */
+               e = NULL;               /* walk extensions in context  */
+               while ( (e = ast_walk_context_extensions(c, e)) ) {
+                       struct ast_exten *p;
 
-                               /* walk ignore patterns and write info ... */
-                               for (ip=ast_walk_context_ignorepats(c, NULL); ip; ip=ast_walk_context_ignorepats(c, ip)) {
-                                       const char *ipname = ast_get_ignorepat_name(ip);
-                                       char ignorepat[AST_MAX_EXTENSION];
-
-                                       snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
-                                       if ((!exten) || ast_extension_match(ignorepat, exten)) {
-                                               dpc->total_items++;
-                                               manager_dpsendack(s, m, &sentpositivemanagerack);
-                                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
-                                               astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
-                                               astman_append(s, "\r\n");
-                                       }
-                               }
-                               if (!rinclude) {
-                                       for (sw = ast_walk_context_switches(c, NULL); sw; sw = ast_walk_context_switches(c, sw)) {
-                                               dpc->total_items++;
-                                               manager_dpsendack(s, m, &sentpositivemanagerack);
-                                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
-                                               astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw)); 
-                                               astman_append(s, "\r\n");
-                                               if (option_debug > 2)
-                                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Found Switch : %s \n", buf);
-                                       }
+                       /* looking for extension? is this our extension? */
+                       if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
+                               /* not the one we are looking for, continue */
+                               if (option_debug > 2)
+                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
+                               continue;
+                       }
+                       if (option_debug > 2)
+                               ast_log(LOG_DEBUG, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
+
+                       dpc->extension_existence = 1;
+
+                       /* may we print context info? */        
+                       dpc->total_context++;
+                       dpc->total_exten++;
+
+                       p = NULL;               /* walk next extension peers */
+                       while ( (p = ast_walk_extension_priorities(e, p)) ) {
+                               int prio = ast_get_extension_priority(p);
+
+                               dpc->total_prio++;
+                               if (!dpc->total_items++)
+                                       manager_dpsendack(s, m);
+                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                               astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
+
+                               /* XXX maybe make this conditional, if p != e ? */
+                               if (ast_get_extension_label(p))
+                                       astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
+
+                               if (prio == PRIORITY_HINT) {
+                                       astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
+                               } else {
+                                       astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
                                }
-       
-                               ast_unlock_context(c);
+                               astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
+                       }
+               }
 
-                       } else if (option_debug > 2) {
-                               ast_log(LOG_DEBUG, "manager_show_dialplan: Failed to lock context\n");
+               i = NULL;               /* walk included and write info ... */
+               while ( (i = ast_walk_context_includes(c, i)) ) {
+                       if (exten) {
+                               /* Check all includes for the requested extension */
+                               manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
+                       } else {
+                               if (!dpc->total_items++)
+                                       manager_dpsendack(s, m);
+                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                               astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
+                               astman_append(s, "\r\n");
+                               if (option_debug > 2)
+                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
                        }
                }
-       } 
+
+               ip = NULL;      /* walk ignore patterns and write info ... */
+               while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
+                       const char *ipname = ast_get_ignorepat_name(ip);
+                       char ignorepat[AST_MAX_EXTENSION];
+
+                       snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
+                       if (!exten || ast_extension_match(ignorepat, exten)) {
+                               if (!dpc->total_items++)
+                                       manager_dpsendack(s, m);
+                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                               astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
+                               astman_append(s, "\r\n");
+                       }
+               }
+               if (!rinclude) {
+                       struct ast_sw *sw = NULL;
+                       while ( (sw = ast_walk_context_switches(c, sw)) ) {
+                               if (!dpc->total_items++)
+                                       manager_dpsendack(s, m);
+                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                               astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw)); 
+                               astman_append(s, "\r\n");
+                               if (option_debug > 2)
+                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
+                       }
+               }
+
+               ast_unlock_context(c);
+       }
        ast_unlock_contexts();
 
        if (dpc->total_exten == old_total_exten) {
@@ -3591,10 +3579,10 @@ static int manager_show_dialplan_helper(struct mansession *s, struct message *m,
 }
 
 /*! \brief  Manager listing of dial plan */
-static int manager_show_dialplan(struct mansession *s, struct message *m)
+static int manager_show_dialplan(struct mansession *s, const struct message *m)
 {
-       char *exten = NULL, *context = NULL;
-       char *id = astman_get_header(m, "ActionID");
+       const char *exten, *context;
+       const char *id = astman_get_header(m, "ActionID");
        char idtext[256];
        int res;
 
@@ -3603,7 +3591,8 @@ static int manager_show_dialplan(struct mansession *s, struct message *m)
 
        if (id && !ast_strlen_zero(id))
                snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
-
+       else
+               idtext[0] = '\0';
 
        memset(&counters, 0, sizeof(counters));
 
@@ -3659,12 +3648,12 @@ static int handle_show_globals(int fd, int argc, char *argv[])
        int i = 0;
        struct ast_var_t *newvariable;
 
-       ast_mutex_lock(&globalslock);
+       ast_rwlock_rdlock(&globalslock);
        AST_LIST_TRAVERSE (&globals, newvariable, entries) {
                i++;
                ast_cli(fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
        }
-       ast_mutex_unlock(&globalslock);
+       ast_rwlock_unlock(&globalslock);
        ast_cli(fd, "\n    -- %d variables\n", i);
 
        return RESULT_SUCCESS;
@@ -3687,23 +3676,23 @@ static int handle_set_global(int fd, int argc, char *argv[])
  * CLI entries for upper commands ...
  */
 static struct ast_cli_entry pbx_cli[] = {
-       { { "core", "list", "applications", NULL },
+       { { "core", "show", "applications", NULL },
        handle_show_applications, "Shows registered dialplan applications",
        show_applications_help, complete_show_applications },
 
-       { { "core", "list", "functions", NULL },
+       { { "core", "show", "functions", NULL },
        handle_show_functions, "Shows registered dialplan functions",
        show_functions_help },
 
-       { { "core", "list", "switches", NULL },
+       { { "core", "show", "switches", NULL },
        handle_show_switches, "Show alternative switches",
        show_switches_help },
 
-       { { "core", "list", "hints", NULL },
+       { { "core", "show", "hints", NULL },
        handle_show_hints, "Show dialplan hints",
        show_hints_help },
 
-       { { "core", "list", "globals", NULL },
+       { { "core", "show", "globals", NULL },
        handle_show_globals, "Show global dialplan variables",
        show_globals_help },
 
@@ -4501,12 +4490,10 @@ int ast_async_goto(struct ast_channel *chan, const char *context, const char *ex
                /* In order to do it when the channel doesn't really exist within
                   the PBX, we have to make a new channel, masquerade, and start the PBX
                   at the new location */
-               struct ast_channel *tmpchan = ast_channel_alloc(0);
+               struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, "AsyncGoto/%s", chan->name);
                if (!tmpchan)
                        res = -1;
                else {
-                       ast_string_field_build(tmpchan, name, "AsyncGoto/%s", chan->name);
-                       ast_setstate(tmpchan, chan->_state);
                        /* Make formats okay */
                        tmpchan->readformat = chan->readformat;
                        tmpchan->writeformat = chan->writeformat;
@@ -4570,10 +4557,6 @@ static int ext_strncpy(char *dst, const char *src, int len)
        return count;
 }
 
-static void null_datad(void *foo)
-{
-}
-
 /*! \brief add the extension in the priority chain.
  * returns 0 on success, -1 on failure
  */
@@ -4595,7 +4578,8 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
                   replacement?  If so, replace, otherwise, bonk. */
                if (!replace) {
                        ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
-                       tmp->datad(tmp->data);
+                       if (tmp->datad)
+                               tmp->datad(tmp->data);
                        free(tmp);
                        return -1;
                }
@@ -4613,7 +4597,8 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
                if (tmp->priority == PRIORITY_HINT)
                        ast_change_hint(e,tmp);
                /* Destroy the old one */
-               e->datad(e->data);
+               if (e->datad)
+                       e->datad(e->data);
                free(e);
        } else {        /* Slip ourselves in just before e */
                tmp->peer = e;
@@ -4679,12 +4664,12 @@ int ast_add_extension2(struct ast_context *con,
        /* if we are adding a hint, and there are global variables, and the hint
           contains variable references, then expand them
        */
-       ast_mutex_lock(&globalslock);
+       ast_rwlock_rdlock(&globalslock);
        if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) {
                pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf));
                application = expand_buf;
        }
-       ast_mutex_unlock(&globalslock);
+       ast_rwlock_unlock(&globalslock);
 
        length = sizeof(struct ast_exten);
        length += strlen(extension) + 1;
@@ -4697,8 +4682,6 @@ int ast_add_extension2(struct ast_context *con,
                length ++;      /* just the '\0' */
 
        /* Be optimistic:  Build the extension structure first */
-       if (datad == NULL)
-               datad = null_datad;
        if (!(tmp = ast_calloc(1, length)))
                return -1;
 
@@ -4863,7 +4846,7 @@ static void *async_wait(void *data)
 static int ast_pbx_outgoing_cdr_failed(void)
 {
        /* allocate a channel */
-       struct ast_channel *chan = ast_channel_alloc(0);
+       struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0);
 
        if (!chan)
                return -1;  /* failure */
@@ -4896,7 +4879,15 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
        pthread_attr_t attr;
 
        if (sync) {
-               LOAD_OH(oh);
+               oh.context = context;
+               oh.exten = exten;
+               oh.priority = priority;
+               oh.cid_num = cid_num;
+               oh.cid_name = cid_name;
+               oh.account = account;
+               oh.vars = vars;
+               oh.parent_channel = NULL;
+
                chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
                if (channel) {
                        *channel = chan;
@@ -4976,9 +4967,8 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
                        /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
                        /* check if "failed" exists */
                        if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
-                               chan = ast_channel_alloc(0);
+                               chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "OutgoingSpoolFailed");
                                if (chan) {
-                                       ast_string_field_set(chan, name, "OutgoingSpoolFailed");
                                        if (!ast_strlen_zero(context))
                                                ast_copy_string(chan->context, context, sizeof(chan->context));
                                        set_ext_pri(chan, "failed", 1);
@@ -5655,7 +5645,7 @@ static int pbx_builtin_goto(struct ast_channel *chan, void *data)
 }
 
 
-int pbx_builtin_serialize_variables(struct ast_channel *chan, char *buf, size_t size)
+int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
 {
        struct ast_var_t *variables;
        const char *var, *val;
@@ -5664,13 +5654,14 @@ int pbx_builtin_serialize_variables(struct ast_channel *chan, char *buf, size_t
        if (!chan)
                return 0;
 
-       memset(buf, 0, size);
+       (*buf)->used = 0;
+       (*buf)->str[0] = '\0';
 
        AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
                if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
                   /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
                   ) {
-                       if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
+                       if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
                                ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
                                break;
                        } else
@@ -5698,7 +5689,7 @@ const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name
                if (!places[i])
                        continue;
                if (places[i] == &globals)
-                       ast_mutex_lock(&globalslock);
+                       ast_rwlock_rdlock(&globalslock);
                AST_LIST_TRAVERSE(places[i], variables, entries) {
                        if (!strcmp(name, ast_var_name(variables))) {
                                ret = ast_var_value(variables);
@@ -5706,7 +5697,7 @@ const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name
                        }
                }
                if (places[i] == &globals)
-                       ast_mutex_unlock(&globalslock);
+                       ast_rwlock_unlock(&globalslock);
                if (ret)
                        break;
        }
@@ -5734,10 +5725,10 @@ void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, cons
                        ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
                newvariable = ast_var_assign(name, value);
                if (headp == &globals)
-                       ast_mutex_lock(&globalslock);
+                       ast_rwlock_wrlock(&globalslock);
                AST_LIST_INSERT_HEAD(headp, newvariable, entries);
                if (headp == &globals)
-                       ast_mutex_unlock(&globalslock);
+                       ast_rwlock_unlock(&globalslock);
        }
 }
 
@@ -5765,7 +5756,7 @@ void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const
        }
 
        if (headp == &globals)
-               ast_mutex_lock(&globalslock);
+               ast_rwlock_wrlock(&globalslock);
        AST_LIST_TRAVERSE (headp, newvariable, entries) {
                if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
                        /* there is already such a variable, delete it */
@@ -5783,7 +5774,7 @@ void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const
        }
 
        if (headp == &globals)
-               ast_mutex_unlock(&globalslock);
+               ast_rwlock_unlock(&globalslock);
 }
 
 int pbx_builtin_setvar(struct ast_channel *chan, void *data)
@@ -5861,10 +5852,10 @@ void pbx_builtin_clear_globals(void)
 {
        struct ast_var_t *vardata;
 
-       ast_mutex_lock(&globalslock);
+       ast_rwlock_wrlock(&globalslock);
        while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
                ast_var_delete(vardata);
-       ast_mutex_unlock(&globalslock);
+       ast_rwlock_unlock(&globalslock);
 }
 
 int pbx_checkcondition(const char *condition)