Applied patch by Daniel: "execute"-action can now be performed on call init or on...
[lcr.git] / action.cpp
index 5819670..1c9e4b2 100644 (file)
@@ -142,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);
@@ -2001,14 +2001,57 @@ 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;
+       pid_t pid2;
+       int iWaitStatus;
        char *command = (char *)"";
        char isdn_port[10];
        char *argv[11]; /* check also number of args below */
@@ -2044,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;
        }
 }
@@ -2227,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)