issue #5763
[asterisk/asterisk.git] / apps / app_forkcdr.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Anthony Minessale anthmct@yahoo.com
5  * Development of this app Sponsered/Funded  by TAAN Softworks Corp
6  *
7  * See http://www.asterisk.org for more information about
8  * the Asterisk project. Please do not directly contact
9  * any of the maintainers of this project for assistance;
10  * the project provides a web site, mailing lists and IRC
11  * channels for your use.
12  *
13  * This program is free software, distributed under the terms of
14  * the GNU General Public License Version 2. See the LICENSE file
15  * at the top of the source tree.
16  */
17
18 /*! \file
19  *
20  * \brief Fork CDR application
21  * 
22  * \ingroup applications
23  */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/file.h"
35 #include "asterisk/logger.h"
36 #include "asterisk/channel.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/cdr.h"
39 #include "asterisk/module.h"
40
41 static char *tdesc = "Fork The CDR into 2 separate entities.";
42 static char *app = "ForkCDR";
43 static char *synopsis = 
44 "Forks the Call Data Record";
45 static char *descrip = 
46 "  ForkCDR([options]):  Causes the Call Data Record to fork an additional\n"
47         "cdr record starting from the time of the fork call\n"
48 "If the option 'v' is passed all cdr variables will be passed along also.\n"
49 "";
50
51
52 STANDARD_LOCAL_USER;
53
54 LOCAL_USER_DECL;
55
56 static void ast_cdr_fork(struct ast_channel *chan) 
57 {
58         struct ast_cdr *cdr;
59         struct ast_cdr *newcdr;
60         struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS };
61
62         cdr = chan->cdr;
63
64         while (cdr->next)
65                 cdr = cdr->next;
66         
67         if (!(newcdr = ast_cdr_dup(cdr)))
68                 return;
69         
70         ast_cdr_append(cdr, newcdr);
71         ast_cdr_reset(newcdr, &flags);
72         
73         if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
74                 ast_cdr_free_vars(cdr, 0);
75         
76         ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
77 }
78
79 static int forkcdr_exec(struct ast_channel *chan, void *data)
80 {
81         int res = 0;
82         struct localuser *u;
83
84         if (!chan->cdr) {
85                 ast_log(LOG_WARNING, "Channel does not have a CDR\n");
86                 return 0;
87         }
88
89         LOCAL_USER_ADD(u);
90
91         if (!ast_strlen_zero(data))
92                 ast_set2_flag(chan->cdr, strchr(data, 'v'), AST_CDR_FLAG_KEEP_VARS);
93         
94         ast_cdr_fork(chan);
95
96         LOCAL_USER_REMOVE(u);
97         return res;
98 }
99
100 int unload_module(void)
101 {
102         int res;
103
104         res = ast_unregister_application(app);
105
106         STANDARD_HANGUP_LOCALUSERS;
107
108         return res;     
109 }
110
111 int load_module(void)
112 {
113         return ast_register_application(app, forkcdr_exec, synopsis, descrip);
114 }
115
116 char *description(void)
117 {
118         return tdesc;
119 }
120
121 int usecount(void)
122 {
123         int res;
124         STANDARD_USECOUNT(res);
125         return res;
126 }
127
128 char *key()
129 {
130         return ASTERISK_GPL_KEY;
131 }