From 64143650bc9c04fadc99694c499cf34750bc2804 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 6 Apr 2009 20:20:09 +0200 Subject: [PATCH] Applied patch by Daniel: "execute"-action can now be performed on call init or on call hangup. A special parameter allows that. -> 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 | 3 +++ action.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- apppbx.h | 2 ++ route.c | 24 ++++++++++++++++++++++-- route.h | 8 +++++++- 5 files changed, 92 insertions(+), 6 deletions(-) diff --git a/README b/README index 6027472..75a8913 100644 --- 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. diff --git a/action.cpp b/action.cpp index bd7239e..1c9e4b2 100644 --- a/action.cpp +++ b/action.cpp @@ -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; } } diff --git a/apppbx.h b/apppbx.h index 4956d7e..78355b5 100644 --- 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 --- a/route.c +++ b/route.c @@ -239,6 +239,9 @@ struct param_defs param_defs[] = { { PARAM_EXTEN, "exten", PARAM_TYPE_STRING, "exten=", "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 --- 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!!! -- 2.13.6