/* * backticks Application For Asterisk * * Copyright (c) 2004-2007 Anthony Minessale II * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include static char *tdesc = "backticks"; static char *app = "BackTicks"; static char *synopsis = "Execute a shell command and save the result as a variable."; static char *desc = "" " Backticks(|)\n\n" "Be sure to include a full path!\n" ; STANDARD_LOCAL_USER; LOCAL_USER_DECL; static char *do_backticks(char *command, char *buf, size_t len) { int fds[2], pid = 0; char *ret = NULL; memset(buf, 0, len); if (pipe(fds)) { ast_log(LOG_WARNING, "Pipe/Exec failed\n"); } else { /* good to go*/ pid = fork(); if (pid < 0) { /* ok maybe not */ ast_log(LOG_WARNING, "Fork failed\n"); close(fds[0]); close(fds[1]); } else if (pid) { /* parent */ close(fds[1]); read(fds[0], buf, len); close(fds[0]); ret = buf; } else { /* child */ char *argv[255] = {0}; int argc = 0; char *p; char *mycmd = ast_strdupa(command); close(fds[0]); dup2(fds[1], STDOUT_FILENO); argv[argc++] = mycmd; do { if ((p = strchr(mycmd, ' '))) { *p = '\0'; mycmd = ++p; argv[argc++] = mycmd; } } while (p); close(fds[1]); execv(argv[0], argv); /* DoH! */ ast_log(LOG_ERROR, "exec of %s failed\n", argv[0]); exit(0); } } return buf; } static int backticks_exec(struct ast_channel *chan, void *data) { int res = 0; struct localuser *u; const char *usage = "Usage: Backticks(|)"; char buf[1024], *argv[2], *mydata; int argc = 0; if (!data) { ast_log(LOG_WARNING, "%s\n", usage); return -1; } LOCAL_USER_ADD(u); /* Do our thing here */ if (!(mydata = ast_strdupa(data))) { ast_log(LOG_ERROR, "Memory Error!\n"); res = -1; } else { if((argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]))) < 2) { ast_log(LOG_WARNING, "%s\n", usage); res = -1; } if (do_backticks(argv[1], buf, sizeof(buf))) { pbx_builtin_setvar_helper(chan, argv[0], buf); } else { ast_log(LOG_WARNING, "No Data!\n"); res = -1; } } LOCAL_USER_REMOVE(u); return res; } static char *function_backticks(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) { char *ret = NULL; if (do_backticks(data, buf, len)) { ret = buf; } return ret; } static struct ast_custom_function backticks_function = { .name = "BACKTICKS", .desc = "Executes a shell command and evaluates to the result.", .syntax = "BACKTICKS()", .synopsis = "Executes a shell command.", .read = function_backticks }; int unload_module(void) { STANDARD_HANGUP_LOCALUSERS; ast_custom_function_unregister(&backticks_function); return ast_unregister_application(app); } int load_module(void) { ast_custom_function_register(&backticks_function); return ast_register_application(app, backticks_exec, synopsis, desc); } char *description(void) { return tdesc; } int usecount(void) { int res; STANDARD_USECOUNT(res); return res; } char *key() { return ASTERISK_GPL_KEY; }