/* * Asterisk -- A telephony toolkit for Linux. * * backticks Application For Asterisk * * Copyright (C) 2005, Anthony Minessale II * * Anthony Minessale II * * This program is free software, distributed under the terms of * the GNU General Public License */ #include #include #include #include #include #include #include #include #include #include #include #include #define AST_MODULE "app_backticks" 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" ; 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; 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; } /* 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; } } 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) { ast_module_user_hangup_all(); ast_custom_function_unregister(&backticks_function); return ast_unregister_application(app); } int load_module(void) { ast_custom_function_register(&backticks_function); int res; res = ast_register_application(app, backticks_exec, synopsis, desc); printf("Return value from register: %d\n", res); return res; } char *description(void) { return tdesc; } int usecnt(void) { int res; return res; } char *key() { return ASTERISK_GPL_KEY; } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Execute command and return output");