5d5216960d5878eaf8d4159188409f90f899d0df
[asterisk/asterisk.git] / apps / app_system.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Execute arbitrary system commands
22  * 
23  * \ingroup applications
24  */
25
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <errno.h>
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include "asterisk/lock.h"
37 #include "asterisk/file.h"
38 #include "asterisk/logger.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/module.h"
42 #include "asterisk/app.h"
43 #include "asterisk/options.h"
44
45 static char *tdesc = "Generic System() application";
46
47 static char *app = "System";
48
49 static char *app2 = "TrySystem";
50
51 static char *synopsis = "Execute a system command";
52
53 static char *synopsis2 = "Try executing a system command";
54
55 static char *chanvar = "SYSTEMSTATUS";
56
57 static char *descrip =
58 "  System(command): Executes a command  by  using  system(). If the command\n"
59 "fails, the console should report a fallthrough. \n"
60 "Result of execution is returned in the SYSTEMSTATUS channel variable:\n"
61 "   FAILURE     Could not execute the specified command\n"
62 "   SUCCESS     Specified command successfully executed\n"
63 "\n"
64 "Old behaviour:\n"
65 "If the command itself executes but is in error, and if there exists\n"
66 "a priority n + 101, where 'n' is the priority of the current instance,\n"
67 "then  the  channel  will  be  setup to continue at that priority level.\n"
68 "Note that this jump functionality has been deprecated and will only occur\n"
69 "if the global priority jumping option is enabled in extensions.conf.\n";
70
71 static char *descrip2 =
72 "  TrySystem(command): Executes a command  by  using  system().\n"
73 "on any situation.\n"
74 "Result of execution is returned in the SYSTEMSTATUS channel variable:\n"
75 "   FAILURE     Could not execute the specified command\n"
76 "   SUCCESS     Specified command successfully executed\n"
77 "   APPERROR    Specified command successfully executed, but returned error code\n"
78 "\n"
79 "Old behaviour:\nIf  the command itself executes but is in error, and if\n"
80 "there exists a priority n + 101, where 'n' is the priority of the current\n"
81 "instance, then  the  channel  will  be  setup  to continue at that\n"
82 "priority level.  Otherwise, System will terminate.\n";
83
84 STANDARD_LOCAL_USER;
85
86 LOCAL_USER_DECL;
87
88 static int system_exec_helper(struct ast_channel *chan, void *data, int failmode)
89 {
90         int res=0;
91         struct localuser *u;
92         
93         if (ast_strlen_zero(data)) {
94                 ast_log(LOG_WARNING, "System requires an argument(command)\n");
95                 pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
96                 return failmode;
97         }
98
99         LOCAL_USER_ADD(u);
100
101         /* Do our thing here */
102         res = ast_safe_system((char *)data);
103         if ((res < 0) && (errno != ECHILD)) {
104                 ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
105                 pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
106                 res = failmode;
107         } else if (res == 127) {
108                 ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
109                 pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
110                 res = failmode;
111         } else {
112                 if (res < 0) 
113                         res = 0;
114                 if (option_priority_jumping && res)
115                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
116
117                 if (res != 0)
118                         pbx_builtin_setvar_helper(chan, chanvar, "APPERROR");
119                 else
120                         pbx_builtin_setvar_helper(chan, chanvar, "SUCCESS");
121                 res = 0;
122         } 
123
124         LOCAL_USER_REMOVE(u);
125
126         return res;
127 }
128
129 static int system_exec(struct ast_channel *chan, void *data)
130 {
131         return system_exec_helper(chan, data, -1);
132 }
133
134 static int trysystem_exec(struct ast_channel *chan, void *data)
135 {
136         return system_exec_helper(chan, data, 0);
137 }
138
139 int unload_module(void)
140 {
141         int res;
142
143         res = ast_unregister_application(app);
144         res |= ast_unregister_application(app2);
145         
146         STANDARD_HANGUP_LOCALUSERS;
147
148         return res;
149 }
150
151 int load_module(void)
152 {
153         int res;
154
155         res = ast_register_application(app2, trysystem_exec, synopsis2, descrip2);
156         res |= ast_register_application(app, system_exec, synopsis, descrip);
157
158         return res;
159 }
160
161 char *description(void)
162 {
163         return tdesc;
164 }
165
166 int usecount(void)
167 {
168         int res;
169         STANDARD_USECOUNT(res);
170         return res;
171 }
172
173 char *key()
174 {
175         return ASTERISK_GPL_KEY;
176 }