Fix potential segfault, add support for MacOS X locks
[asterisk/asterisk.git] / manager.c
index ed94d80..c77fec1 100755 (executable)
--- a/manager.c
+++ b/manager.c
@@ -376,18 +376,20 @@ static int action_hangup(struct mansession *s, struct message *m)
                astman_send_error(s, m, "No channel specified");
                return 0;
        }
-       c = ast_channel_walk(NULL);
+       c = ast_channel_walk_locked(NULL);
        while(c) {
                if (!strcasecmp(c->name, name)) {
                        break;
                }
-               c = ast_channel_walk(c);
+               ast_mutex_unlock(&c->lock);
+               c = ast_channel_walk_locked(c);
        }
        if (!c) {
                astman_send_error(s, m, "No such channel");
                return 0;
        }
        ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
+       ast_mutex_unlock(&c->lock);
        astman_send_ack(s, m, "Channel Hungup");
        return 0;
 }
@@ -399,7 +401,7 @@ static int action_status(struct mansession *s, struct message *m)
        struct ast_channel *c;
        char bridge[256];
        astman_send_ack(s, m, "Channel status will follow");
-       c = ast_channel_walk(NULL);
+       c = ast_channel_walk_locked(NULL);
         if (id && strlen(id))
                 snprintf(idText,256,"ActionID: %s\r\n",id);
        while(c) {
@@ -436,7 +438,8 @@ static int action_status(struct mansession *s, struct message *m)
                        c->name, c->callerid ? c->callerid : "<unknown>", 
                        ast_state2str(c->_state), bridge, c->uniqueid, idText);
                }
-               c = ast_channel_walk(c);
+               ast_mutex_unlock(&c->lock);
+               c = ast_channel_walk_locked(c);
        }
        ast_cli(s->fd,
        "Event: StatusComplete\r\n"
@@ -452,6 +455,7 @@ static int action_redirect(struct mansession *s, struct message *m)
        char *exten = astman_get_header(m, "Exten");
        char *context = astman_get_header(m, "Context");
        char *priority = astman_get_header(m, "Priority");
+       struct ast_channel *chan, *chan2 = NULL;
        int pi = 0;
        int res;
        if (!name || !strlen(name)) {
@@ -462,10 +466,20 @@ static int action_redirect(struct mansession *s, struct message *m)
                astman_send_error(s, m, "Invalid priority\n");
                return 0;
        }
-       res = ast_async_goto_by_name(name, context, exten, pi);
+       chan = ast_get_channel_by_name_locked(name);
+       if (!chan) {
+               astman_send_error(s, m, "Channel not existant");
+               return 0;
+       }
+       if (strlen(name2))
+               chan2 = ast_get_channel_by_name_locked(name2);
+       res = ast_async_goto(chan, context, exten, pi);
        if (!res) {
                if (strlen(name2)) {
-                       res = ast_async_goto_by_name(name2, context, exten, pi);
+                       if (chan2)
+                               res = ast_async_goto(chan2, context, exten, pi);
+                       else
+                               res = -1;
                        if (!res)
                                astman_send_ack(s, m, "Dual Redirect successful");
                        else
@@ -474,6 +488,10 @@ static int action_redirect(struct mansession *s, struct message *m)
                        astman_send_ack(s, m, "Redirect successful");
        } else
                astman_send_error(s, m, "Redirect failed");
+       if (chan)
+               ast_mutex_unlock(&chan->lock);
+       if (chan2)
+               ast_mutex_unlock(&chan2->lock);
        return 0;
 }
 
@@ -688,18 +706,20 @@ static int action_timeout(struct mansession *s, struct message *m)
                astman_send_error(s, m, "No timeout specified");
                return 0;
        }
-       c = ast_channel_walk(NULL);
+       c = ast_channel_walk_locked(NULL);
        while(c) {
                if (!strcasecmp(c->name, name)) {
                        break;
                }
-               c = ast_channel_walk(c);
+               ast_mutex_unlock(&c->lock);
+               c = ast_channel_walk_locked(c);
        }
        if (!c) {
                astman_send_error(s, m, "No such channel");
                return 0;
        }
        ast_channel_setwhentohangup(c, timeout);
+       ast_mutex_unlock(&c->lock);
        astman_send_ack(s, m, "Timeout Set");
        return 0;
 }