Applied patch by Daniel: "execute"-action can now be performed on call init or on...
[lcr.git] / action.cpp
index ce741c6..1c9e4b2 100644 (file)
@@ -17,7 +17,7 @@ extern char **environ;
 /*
  * process init 'internal' / 'external' / 'remote' / 'vbox-record' / 'partyline'...
  */
-void EndpointAppPBX::_action_init_call(char *remote)
+int EndpointAppPBX::_action_init_call(char *remote)
 {
        class Join              *join;
        struct port_list        *portlist = ea_endpoint->ep_portlist;
@@ -28,7 +28,7 @@ void EndpointAppPBX::_action_init_call(char *remote)
        {
                if (options.deb & DEBUG_EPOINT)
                        PERROR("EPOINT(%d): We already have a call instance, this should never happen!\n", ea_endpoint->ep_serial);
-               return;
+               return(0);
        }
 
        /* create join */
@@ -51,7 +51,7 @@ void EndpointAppPBX::_action_init_call(char *remote)
                        message_disconnect_port(portlist, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, "");
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        set_tone(portlist,"cause_1b");
-                       return;
+                       return(0);
                }
                join = new JoinRemote(ea_endpoint->ep_serial, remote, admin->sock);
        }
@@ -60,6 +60,7 @@ void EndpointAppPBX::_action_init_call(char *remote)
        if (!join)
                FATAL("No memoy for Join instance.\n");
        ea_endpoint->ep_join_id = join->j_serial;
+       return(1);
 }
 void EndpointAppPBX::action_init_call(void)
 {
@@ -141,7 +142,7 @@ void EndpointAppPBX::action_dialing_internal(void)
        }
 
        /* check if extension exists AND only if not multiple extensions */
-       if (!read_extension(&ext, dialinginfo.id) && !strchr(dialinginfo.id,','))
+       if (!strchr(dialinginfo.id,',') && !read_extension(&ext, dialinginfo.id))
        {
                trace_header("ACTION extension (extension doesn't exist)", DIRECTION_NONE);
                add_trace("extension", NULL, dialinginfo.id);
@@ -358,7 +359,7 @@ void EndpointAppPBX::action_dialing_remote(void)
        char                    context[128] = "";
        char                    remote[32];
 
-       if (e_state == EPOINT_STATE_IN_SETUP && !ea_endpoint->ep_join_id)
+       if (!ea_endpoint->ep_join_id)
        {
                /* no join yet, sending setup */
                if (!(rparam = routeparam(e_action, PARAM_APPLICATION)))
@@ -371,7 +372,8 @@ void EndpointAppPBX::action_dialing_remote(void)
                        return;
                }
                SCPY(remote, rparam->string_value);
-               _action_init_call(remote);
+               if (!_action_init_call(remote))
+                       return;
 
                /* create bearer/caller/dialinginfo */
                memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
@@ -391,6 +393,7 @@ void EndpointAppPBX::action_dialing_remote(void)
                {
                        SCPY(dialinginfo.id, e_extdialing);
                }
+               e_extdialing = e_dialinginfo.id + strlen(e_dialinginfo.id);
                /* send setup to remote */
                trace_header("ACTION remote (setup)", DIRECTION_NONE);
                add_trace("number", NULL, dialinginfo.id);
@@ -985,12 +988,12 @@ void EndpointAppPBX::_action_redial_reply(int in)
        {
                /* find next entry */
                e_select++;
-               if (e_select >= MAX_REMEMBER)
+               if (e_select >= MAX_REMEMBER) {
                        e_select--;
-               else if (in)
+               } else if (in) {
                        if (e_ext.last_in[e_select][0] == '\0')
                                e_select--;
-               else
+               else
                        if (e_ext.last_out[e_select][0] == '\0')
                                e_select--;
 
@@ -1500,7 +1503,7 @@ void EndpointAppPBX::action_dialing_calculator(void)
        struct port_list *portlist = ea_endpoint->ep_portlist;
        struct lcr_msg *message;
        double value1, value2, v, sign1;
-       int komma1, komma2, k, state, mode, first;
+       int komma1, komma2, k, state, mode = 0, first;
        char *p;
 
        portlist = ea_endpoint->ep_portlist;
@@ -1998,15 +2001,59 @@ void EndpointAppPBX::action_dialing_setforward(void)
 {
 }
 
+/*
+ * process init 'execute'
+ */ 
+void EndpointAppPBX::action_init_execute(void)
+{
+       struct route_param *rparam;
+       int executeon = INFO_ON_HANGUP;  /* Use Hangup as a default for compatibility */
+       
+       /* Get the execute on parameter */
+       if ((rparam = routeparam(e_action, PARAM_ON)))
+       executeon = rparam->integer_value;
+
+       /* Execute this action if init was specified */
+       if (executeon == INFO_ON_INIT)
+       {
+               trace_header("ACTION execute ON init", DIRECTION_NONE);
+               end_trace();
+               action_execute();
+       }
+}
 
 /*
  * process hangup 'execute'
- */
+ */ 
 void EndpointAppPBX::action_hangup_execute(void)
 {
        struct route_param *rparam;
+       int executeon = INFO_ON_HANGUP;  /* Use Hangup as a default for compatibility */
+       
+       /* Get the execute on parameter */
+       if ((rparam = routeparam(e_action, PARAM_ON)))
+       executeon = rparam->integer_value;
+
+       /* Execute this action if init was specified */
+       if (executeon == INFO_ON_HANGUP)
+       {
+               trace_header("ACTION execute ON hangup", DIRECTION_NONE);
+               end_trace();
+               action_execute();
+       }
+}
+
+/*
+ * process 'execute' from action_init_execute or action_hangup_execute
+ */
+void EndpointAppPBX::action_execute(void)
+{
+       struct route_param *rparam;
        pid_t pid;
-       char *command = "", isdn_port[10];
+       pid_t pid2;
+       int iWaitStatus;
+       char *command = (char *)"";
+       char isdn_port[10];
        char *argv[11]; /* check also number of args below */
        int i = 0;
 
@@ -2019,8 +2066,8 @@ void EndpointAppPBX::action_hangup_execute(void)
                end_trace();
                return;
        }
-       argv[i++] = "/bin/sh";
-       argv[i++] = "-c";
+       argv[i++] = (char *)"/bin/sh";
+       argv[i++] = (char *)"-c";
        argv[i++] = command;
        argv[i++] = command;
        if ((rparam = routeparam(e_action, PARAM_PARAM)))
@@ -2028,7 +2075,7 @@ void EndpointAppPBX::action_hangup_execute(void)
                argv[i++] = rparam->string_value;
        }
        argv[i++] = e_extdialing;
-       argv[i++] = numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international);
+       argv[i++] = (char *)numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international);
        argv[i++] = e_callerinfo.extension;
        argv[i++] = e_callerinfo.name;
        SPRINT(isdn_port, "%d", e_callerinfo.isdn_port);
@@ -2040,12 +2087,24 @@ void EndpointAppPBX::action_hangup_execute(void)
                        end_trace();
                        break;
                case 0:
-                       execve("/bin/sh", argv, environ);
-                       break;
+                       /* To be shure there are no zombies created double fork */
+                       if ((pid2 = fork()) == 0)
+                       {
+                               execve("/bin/sh", argv, environ);
+                       }
+                       else
+                       {
+                               /* Exit immediately and release the waiting parent. The subprocess falls to init because the parent died */
+                               exit(0);
+                       }
+                       break;
                default:
                        trace_header("ACTION execute", DIRECTION_NONE);
                        add_trace("command", NULL, "%s", command);
                        end_trace();
+
+                       /* Wait for the pid. The forked process will exit immediately so there is no problem waiting. */
+                       waitpid(pid, &iWaitStatus, 0);
                        break;
        }
 }
@@ -2057,7 +2116,7 @@ void EndpointAppPBX::action_hangup_execute(void)
 void EndpointAppPBX::action_hangup_file(void)
 {
        struct route_param *rparam;
-       char *file, *content, *mode;
+       const char *file, *content, *mode;
        FILE *fp;
 
        /* get file / content */
@@ -2223,7 +2282,7 @@ void EndpointAppPBX::process_dialing(void)
 
 //PDEBUG(~0, "HANG-BUG-DEBUGGING: before action-timeout processing\n");
        /* process timeout */
-       if (e_action_timeout)
+       if (e_action && e_action_timeout) /* e_action may be NULL, but e_action_timeout may still be set and must be ignored */
        {
                e_action_timeout = 0;
                if (e_state == EPOINT_STATE_CONNECT)