Applied patch by Daniel: "execute"-action can now be performed on call init or on...
authorAndreas Eversberg <andreas@eversberg.eu>
Mon, 6 Apr 2009 18:20:09 +0000 (20:20 +0200)
committerAndreas Eversberg <andreas@eversberg.eu>
Mon, 6 Apr 2009 18:20:09 +0000 (20:20 +0200)
-> Forking of executed program is now performed without getting zombie process.

modified:   README
modified:   action.cpp
modified:   apppbx.h
modified:   route.c
modified:   route.h

README
action.cpp
apppbx.h
route.c
route.h

diff --git a/README b/README
index 6027472..75a8913 100644 (file)
--- a/README
+++ b/README
@@ -483,4 +483,7 @@ Changes after Version 1.4 release
 - chan_lcr: Open b-channel if asterisk indicates "PROGRESS".
   -> Also if tones are available, asterisk gets "PROGRESS" indication.
 - lcradmin displays TEI values in NT-mode PTMP
+- Added patch from Daniel
+  -> Improved forking
+  -> Execution action can now be done on call init or on call hangup.
 
index bd7239e..1c9e4b2 100644 (file)
@@ -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;
        }
 }
index 4956d7e..78355b5 100644 (file)
--- a/apppbx.h
+++ b/apppbx.h
@@ -289,7 +289,9 @@ class EndpointAppPBX : public EndpointApp
        void action_dialing_help(void);
        void action_dialing_deflect(void);
        void action_dialing_setforward(void);
+       void action_init_execute(void);
        void action_hangup_execute(void);
+       void action_execute(void);
        void action_hangup_file(void);
        void action_init_pick(void);
        void action_dialing_password(void);
diff --git a/route.c b/route.c
index 8d821ec..017a55c 100644 (file)
--- a/route.c
+++ b/route.c
@@ -239,6 +239,9 @@ struct param_defs param_defs[] = {
        { PARAM_EXTEN,
          "exten",      PARAM_TYPE_STRING,
          "exten=<extension>", "Give exten parameter to the remote application. (overrides dialed number)"},
+       { PARAM_ON,
+         "on", PARAM_TYPE_STRING,
+         "on=[init|hangup]", "Defines if the action is executed on call init or on hangup."},
        { 0, NULL, 0, NULL, NULL}
 };
 
@@ -347,8 +350,8 @@ struct action_defs action_defs[] = {
          NULL},
 //       "The call forward is set within the telephone network of the external line."},
        { ACTION_EXECUTE,
-         "execute",    NULL, NULL, &EndpointAppPBX::action_hangup_execute,
-         PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM,
+         "execute",    &EndpointAppPBX::action_init_execute, NULL, &EndpointAppPBX::action_hangup_execute,
+         PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM | PARAM_ON,
          "Executes the given script file. The file must terminate quickly, because it will halt the PBX."},
        { ACTION_FILE,
          "file",       NULL, NULL, &EndpointAppPBX::action_hangup_file,
@@ -1684,6 +1687,7 @@ struct route_ruleset *ruleset_parse(void)
                                case PARAM_TYPE_DESTIN:
                                case PARAM_TYPE_TYPE:
                                case PARAM_TYPE_YESNO:
+                               case PARAM_TYPE_ON:
                                key[0] = '\0';
                                if (*p==',' || *p==' ' || *p=='\0')
                                {
@@ -1722,6 +1726,22 @@ struct route_ruleset *ruleset_parse(void)
                                        SPRINT(failure, "Caller ID type '%s' unknown.", key);
                                        goto parse_error;
                                }
+                               if (param_defs[index].type == PARAM_TYPE_ON)
+                               {
+                                       param->value_type = VALUE_TYPE_INTEGER;
+                                       if (!strcasecmp(key, "init"))
+                                       {
+                                               param->integer_value = INFO_ON_INIT;
+                                               break;
+                                       }
+                                       if (!strcasecmp(key, "hangup"))
+                                       {
+                                               param->integer_value = INFO_ON_HANGUP;
+                                               break;
+                                       }
+                                       SPRINT(failure, "Execute on '%s' unknown.", key);
+                                       goto parse_error;
+                               }
                                if (param_defs[index].type == PARAM_TYPE_CAPABILITY)
                                {
                                        param->value_type = VALUE_TYPE_INTEGER;
diff --git a/route.h b/route.h
index 06fb54f..837aebd 100644 (file)
--- a/route.h
+++ b/route.h
@@ -89,6 +89,12 @@ enum { /* how to parse text file during startup */
        PARAM_TYPE_PORTS,
        PARAM_TYPE_TYPE,
        PARAM_TYPE_CALLERIDTYPE,
+       PARAM_TYPE_ON,
+};
+
+enum { /* defines when a statement should be executed */
+       INFO_ON_INIT,
+       INFO_ON_HANGUP,
 };
 
 /* parameter ID bits */
@@ -139,7 +145,7 @@ enum { /* how to parse text file during startup */
 #define PARAM_APPLICATION      (1LL<<44)
 #define PARAM_CONTEXT          (1LL<<45)
 #define PARAM_EXTEN            (1LL<<46)
-
+#define PARAM_ON               (1LL<<47)
 
 /* action index
  * NOTE: The given index is the actual entry number of action_defs[], so add/remove both lists!!!