update docs to reflect that priority jumping only occurs when the global
[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 /*
20  *
21  * Execute arbitrary system commands
22  * 
23  */
24
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <errno.h>
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 #include "asterisk/lock.h"
36 #include "asterisk/file.h"
37 #include "asterisk/logger.h"
38 #include "asterisk/channel.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/module.h"
41 #include "asterisk/app.h"
42 #include "asterisk/options.h"
43
44 static char *tdesc = "Generic System() application";
45
46 static char *app = "System";
47
48 static char *app2 = "TrySystem";
49
50 static char *synopsis = "Execute a system command";
51
52 static char *synopsis2 = "Try executing a system command";
53
54 static char *chanvar = "SYSTEMSTATUS";
55
56 static char *descrip =
57 "  System(command): Executes a command  by  using  system(). Returns -1 on\n"
58 "failure to execute the specified command. \n"
59 "Result of execution is returned in the SYSTEMSTATUS channel variable:\n"
60 "   FAILURE     Could not execute the specified command\n"
61 "   SUCCESS     Specified command successfully executed\n"
62 "\n"
63 "Old behaviour:\n"
64 "If the command itself executes but is in error, and if there exists\n"
65 "a priority n + 101, where 'n' is the priority of the current instance,\n"
66 "then  the  channel  will  be  setup to continue at that priority level.\n"
67 "Note that this jump functionality has been deprecated and will only occur\n"
68 "if the global priority jumping option is enabled in extensions.conf.\n"
69 " Otherwise, System returns 0.\n";
70
71 static char *descrip2 =
72 "  TrySystem(command): Executes a command  by  using  system(). Returns 0\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 returns 0.\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         if (!data) {
93                 ast_log(LOG_WARNING, "System requires an argument(command)\n");
94                 pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
95                 return failmode;
96         }
97         LOCAL_USER_ADD(u);
98
99         /* Do our thing here */
100         res = ast_safe_system((char *)data);
101         if ((res < 0) && (errno != ECHILD)) {
102                 ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
103                 pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
104                 res = failmode;
105         } else if (res == 127) {
106                 ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
107                 pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
108                 res = failmode;
109         } else {
110                 if (res < 0) 
111                         res = 0;
112                 if (option_priority_jumping && res)
113                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
114
115                 if (res != 0)
116                         pbx_builtin_setvar_helper(chan, chanvar, "APPERROR");
117                 else
118                         pbx_builtin_setvar_helper(chan, chanvar, "SUCCESS");
119                 res = 0;
120         } 
121
122         LOCAL_USER_REMOVE(u);
123         return res;
124 }
125
126 static int system_exec(struct ast_channel *chan, void *data)
127 {
128         return system_exec_helper(chan, data, -1);
129 }
130
131 static int trysystem_exec(struct ast_channel *chan, void *data)
132 {
133         return system_exec_helper(chan, data, 0);
134 }
135
136 int unload_module(void)
137 {
138         STANDARD_HANGUP_LOCALUSERS;
139         ast_unregister_application(app2);
140         return ast_unregister_application(app);
141 }
142
143 int load_module(void)
144 {
145         ast_register_application(app2, trysystem_exec, synopsis2, descrip2);
146         return ast_register_application(app, system_exec, synopsis, descrip);
147 }
148
149 char *description(void)
150 {
151         return tdesc;
152 }
153
154 int usecount(void)
155 {
156         int res;
157         STANDARD_USECOUNT(res);
158         return res;
159 }
160
161 char *key()
162 {
163         return ASTERISK_GPL_KEY;
164 }