1 /*
2 * Copyright (C) 2001-2003 FhG Fokus
3 *
4 * This file is part of Kamailio, a free SIP server.
5 *
6 * Kamailio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
10 *
11 * Kamailio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 /*!
23 * \file
24 * \brief Exec module:: Module interface
25 * \ingroup exec
26 * Module: \ref exec
27 */
28
29 /**
30 * @defgroup exec Execute external applications
31 * @brief Kamailio exec module
32 *
33 * The exec module allows external commands to be executed from a Kamailio script.
34 * The commands may be any valid shell commands--the command string is passed to the
35 * shell using “popen” command. Kamailio passes additional information about the request
36 * in environment variables.
37 *
38 */
39
40
41 #include <stdio.h>
42 #include <strings.h>
43 #include <errno.h>
44 #include <stdlib.h>
45 #include <sys/types.h>
46 /*
47 #include <sys/resource.h>
48 */
49 #include <sys/wait.h>
50 #include "../../core/mem/mem.h"
51 #include "../../core/error.h"
52 #include "../../core/config.h"
53 #include "../../core/parser/msg_parser.h"
54 #include "../../core/dprint.h"
55 #include "../../core/dset.h"
56 #include "../../core/action.h"
57 #include "../../core/usr_avp.h"
58
59 #include "exec.h"
60
exec_msg(struct sip_msg * msg,char * cmd)61 int exec_msg(struct sip_msg *msg, char *cmd)
62 {
63 FILE *pipe;
64 int exit_status;
65 int ret;
66
67 ret = -1; /* pessimist: assume error */
68 pipe = popen(cmd, "w");
69 if(pipe == NULL) {
70 LM_ERR("cannot open pipe: %s\n", cmd);
71 ser_error = E_EXEC;
72 return -1;
73 }
74
75 if(fwrite(msg->buf, 1, msg->len, pipe) != msg->len) {
76 LM_ERR("failed to write to pipe\n");
77 ser_error = E_EXEC;
78 goto error01;
79 }
80 /* success */
81 ret = 1;
82
83 error01:
84 if(ferror(pipe)) {
85 LM_ERR("pipe: %s\n", strerror(errno));
86 ser_error = E_EXEC;
87 ret = -1;
88 }
89 exit_status = pclose(pipe);
90 if(WIFEXITED(exit_status)) { /* exited properly .... */
91 /* return false if script exited with non-zero status */
92 if(WEXITSTATUS(exit_status) != 0)
93 ret = -1;
94 } else { /* exited erroneously */
95 LM_ERR("cmd %s failed. exit_status=%d, errno=%d: %s\n", cmd,
96 exit_status, errno, strerror(errno));
97 ret = -1;
98 }
99 return ret;
100 }
101
exec_str(struct sip_msg * msg,char * cmd,char * param,int param_len)102 int exec_str(struct sip_msg *msg, char *cmd, char *param, int param_len)
103 {
104
105 struct action act;
106 struct run_act_ctx ra_ctx;
107 int cmd_len;
108 FILE *pipe;
109 char *cmd_line;
110 int ret;
111 int l1;
112 static char uri_line[MAX_URI_SIZE + 1];
113 int uri_cnt;
114 str uri;
115 int exit_status;
116
117 /* pessimist: assume error by default */
118 ret = -1;
119
120 l1 = strlen(cmd);
121 if(param_len > 0)
122 cmd_len = l1 + param_len + 4;
123 else
124 cmd_len = l1 + 1;
125 cmd_line = pkg_malloc(cmd_len);
126 if(cmd_line == 0) {
127 ret = ser_error = E_OUT_OF_MEM;
128 LM_ERR("no pkg mem for command\n");
129 goto error00;
130 }
131
132 /* 'command parameter \0' */
133 memcpy(cmd_line, cmd, l1);
134 if(param_len > 0) {
135 cmd_line[l1] = ' ';
136 cmd_line[l1 + 1] = '\'';
137 memcpy(cmd_line + l1 + 2, param, param_len);
138 cmd_line[l1 + param_len + 2] = '\'';
139 cmd_line[l1 + param_len + 3] = 0;
140 } else {
141 cmd_line[l1] = 0;
142 }
143
144 pipe = popen(cmd_line, "r");
145 if(pipe == NULL) {
146 LM_ERR("cannot open pipe: %s\n", cmd_line);
147 ser_error = E_EXEC;
148 goto error01;
149 }
150
151 /* read now line by line */
152 uri_cnt = 0;
153 while(fgets(uri_line, MAX_URI_SIZE, pipe) != NULL) {
154 uri.s = uri_line;
155 uri.len = strlen(uri.s);
156 /* trim from right */
157 while(uri.len
158 && (uri.s[uri.len - 1] == '\r' || uri.s[uri.len - 1] == '\n'
159 || uri.s[uri.len - 1] == '\t'
160 || uri.s[uri.len - 1] == ' ')) {
161 LM_DBG("rtrim\n");
162 uri.len--;
163 }
164 /* skip empty line */
165 if(uri.len == 0)
166 continue;
167 /* ZT */
168 uri.s[uri.len] = 0;
169 if(uri_cnt == 0) {
170 memset(&act, 0, sizeof(act));
171 act.type = SET_URI_T;
172 act.val[0].type = STRING_ST;
173 act.val[0].u.string = uri.s;
174 init_run_actions_ctx(&ra_ctx);
175 if(do_action(&ra_ctx, &act, msg) < 0) {
176 LM_ERR("the action for has failed\n");
177 ser_error = E_OUT_OF_MEM;
178 goto error02;
179 }
180 } else {
181 if(append_branch(msg, &uri, 0, 0, Q_UNSPECIFIED, 0, 0, 0, 0, 0, 0)
182 == -1) {
183 LM_ERR("append_branch failed; too many or too long URIs?\n");
184 goto error02;
185 }
186 }
187 uri_cnt++;
188 }
189 if(uri_cnt == 0) {
190 LM_ERR("no uri from %s\n", cmd_line);
191 goto error02;
192 }
193 /* success */
194 ret = 1;
195
196 error02:
197 if(ferror(pipe)) {
198 LM_ERR("in pipe: %s\n", strerror(errno));
199 ser_error = E_EXEC;
200 ret = -1;
201 }
202 exit_status = pclose(pipe);
203 if(WIFEXITED(exit_status)) { /* exited properly .... */
204 /* return false if script exited with non-zero status */
205 if(WEXITSTATUS(exit_status) != 0)
206 ret = -1;
207 } else { /* exited erroneously */
208 LM_ERR("cmd %s failed. exit_status=%d, errno=%d: %s\n", cmd,
209 exit_status, errno, strerror(errno));
210 ret = -1;
211 }
212 error01:
213 pkg_free(cmd_line);
214 error00:
215 return ret;
216 }
217
218
exec_avp(struct sip_msg * msg,char * cmd,pvname_list_p avpl)219 int exec_avp(struct sip_msg *msg, char *cmd, pvname_list_p avpl)
220 {
221 int_str avp_val;
222 int_str avp_name;
223 unsigned short avp_type;
224 FILE *pipe;
225 int ret;
226 char res_line[MAX_URI_SIZE + 1];
227 str res;
228 int exit_status;
229 int i;
230 pvname_list_t *crt;
231
232 /* pessimist: assume error by default */
233 ret = -1;
234
235 pipe = popen(cmd, "r");
236 if(pipe == NULL) {
237 LM_ERR("cannot open pipe: %s\n", cmd);
238 ser_error = E_EXEC;
239 return ret;
240 }
241
242 /* read now line by line */
243 i = 0;
244 crt = avpl;
245 while(fgets(res_line, MAX_URI_SIZE, pipe) != NULL) {
246 res.s = res_line;
247 res.len = strlen(res.s);
248 /* trim from right */
249 while(res.len
250 && (res.s[res.len - 1] == '\r' || res.s[res.len - 1] == '\n'
251 || res.s[res.len - 1] == '\t'
252 || res.s[res.len - 1] == ' ')) {
253 res.len--;
254 }
255 /* skip empty line */
256 if(res.len == 0)
257 continue;
258 /* ZT */
259 res.s[res.len] = 0;
260
261 avp_type = 0;
262 if(crt == NULL) {
263 avp_name.n = i + 1;
264 } else {
265 if(pv_get_avp_name(msg, &(crt->sname.pvp), &avp_name, &avp_type)
266 != 0) {
267 LM_ERR("can't get item name [%d]\n", i);
268 goto error;
269 }
270 }
271
272 avp_type |= AVP_VAL_STR;
273 avp_val.s = res;
274
275 if(add_avp(avp_type, avp_name, avp_val) != 0) {
276 LM_ERR("unable to add avp\n");
277 goto error;
278 }
279
280 if(crt)
281 crt = crt->next;
282
283 i++;
284 }
285 if(i == 0) {
286 LM_DBG("no result from %s\n", cmd);
287 } else {
288 LM_DBG("%d results from %s\n", i, cmd);
289 }
290 /* success */
291 ret = 1;
292
293 error:
294 if(ferror(pipe)) {
295 LM_ERR("pipe: %d/%s\n", errno, strerror(errno));
296 ser_error = E_EXEC;
297 ret = -1;
298 }
299 exit_status = pclose(pipe);
300 if(WIFEXITED(exit_status)) { /* exited properly .... */
301 /* return false if script exited with non-zero status */
302 if(WEXITSTATUS(exit_status) != 0)
303 ret = -1;
304 } else { /* exited erroneously */
305 LM_ERR("cmd %s failed. exit_status=%d, errno=%d: %s\n", cmd,
306 exit_status, errno, strerror(errno));
307 ret = -1;
308 }
309 return ret;
310 }
311
exec_cmd(sip_msg_t * msg,char * cmd)312 int exec_cmd(sip_msg_t *msg, char *cmd)
313 {
314 FILE *pipe;
315 int exit_status;
316 int ret;
317
318 pipe = popen(cmd, "r");
319 if(pipe == NULL) {
320 LM_ERR("cannot open pipe: %s\n", cmd);
321 ser_error = E_EXEC;
322 return -1;
323 }
324
325 ret = 1;
326 exit_status = pclose(pipe);
327 if(WIFEXITED(exit_status)) { /* exited properly .... */
328 /* return false if script exited with non-zero status */
329 if(WEXITSTATUS(exit_status) != 0) {
330 LM_DBG("cmd %s with non-zero status - exit_status=%d,"
331 " wexitstatus: %d, errno=%d: %s\n",
332 cmd, exit_status, WEXITSTATUS(exit_status),
333 errno, strerror(errno));
334 ret = -1;
335 }
336 } else { /* exited erroneously */
337 LM_ERR("cmd %s failed. exit_status=%d, wexitstatus: %d, errno=%d: %s\n",
338 cmd, exit_status, WEXITSTATUS(exit_status),
339 errno, strerror(errno));
340 ret = -1;
341 }
342
343 return ret;
344 }
345