remove unnecessary checks before calls to ast_strlen_zero
[asterisk/asterisk.git] / apps / app_read.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 Trivial application to read a variable
22  * 
23  */
24  
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include "asterisk.h"
29
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31
32 #include "asterisk/lock.h"
33 #include "asterisk/file.h"
34 #include "asterisk/logger.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/app.h"
38 #include "asterisk/module.h"
39 #include "asterisk/translate.h"
40 #include "asterisk/options.h"
41 #include "asterisk/utils.h"
42
43 static char *tdesc = "Read Variable Application";
44
45 static char *app = "Read";
46
47 static char *synopsis = "Read a variable";
48
49 static char *descrip = 
50 "  Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n"
51 "Reads a #-terminated string of digits a certain number of times from the\n"
52 "user in to the given variable.\n"
53 "  filename   -- file to play before reading digits.\n"
54 "  maxdigits  -- maximum acceptable number of digits. Stops reading after\n"
55 "                maxdigits have been entered (without requiring the user to\n"
56 "                press the '#' key).\n"
57 "                Defaults to 0 - no limit - wait for the user press the '#' key.\n"
58 "                Any value below 0 means the same. Max accepted value is 255.\n"
59 "  option     -- may be 'skip' to return immediately if the line is not up,\n"
60 "                or 'noanswer' to read digits even if the line is not up.\n"
61 "  attempts   -- if greater than 1, that many attempts will be made in the \n"
62 "                event no data is entered.\n"
63 "  timeout    -- if greater than 0, that value will override the default timeout.\n\n"
64 "Returns -1 on hangup or error and 0 otherwise.\n";
65
66 STANDARD_LOCAL_USER;
67
68 LOCAL_USER_DECL;
69
70 #define ast_next_data(instr,ptr,delim) if((ptr=strchr(instr,delim))) { *(ptr) = '\0' ; ptr++;}
71
72 static int read_exec(struct ast_channel *chan, void *data)
73 {
74         int res = 0;
75         struct localuser *u;
76         char tmp[256];
77         char *timeout = NULL;
78         char *varname = NULL;
79         char *filename = NULL;
80         char *loops;
81         char *maxdigitstr=NULL;
82         char *options=NULL;
83         int option_skip = 0;
84         int option_noanswer = 0;
85         int maxdigits=255;
86         int tries = 1;
87         int to = 0;
88         int x = 0;
89         char *argcopy = NULL;
90         char *args[8];
91
92         if (ast_strlen_zero(data)) {
93                 ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
94                 return -1;
95         }
96
97         LOCAL_USER_ADD(u);
98         
99         argcopy = ast_strdupa(data);
100         if (!argcopy) {
101                 ast_log(LOG_ERROR, "Out of memory\n");
102                 LOCAL_USER_REMOVE(u);
103                 return -1;
104         }
105
106         if (ast_separate_app_args(argcopy, '|', args, sizeof(args) / sizeof(args[0])) < 1) {
107                 ast_log(LOG_WARNING, "Cannot Parse Arguments.\n");
108                 LOCAL_USER_REMOVE(u);
109                 return -1;
110         }
111
112         varname = args[x++];
113         filename = args[x++];
114         maxdigitstr = args[x++];
115         options = args[x++];
116         loops = args[x++];
117         timeout = args[x++];
118         
119         if (options) { 
120                 if (!strcasecmp(options, "skip"))
121                         option_skip = 1;
122                 else if (!strcasecmp(options, "noanswer"))
123                         option_noanswer = 1;
124                 else {
125                         if (strchr(options, 's'))
126                                 option_skip = 1;
127                         if (strchr(options, 'n'))
128                                 option_noanswer = 1;
129                 }
130         }
131
132         if(loops) {
133                 tries = atoi(loops);
134                 if(tries <= 0)
135                         tries = 1;
136         }
137
138         if(timeout) {
139                 to = atoi(timeout);
140                 if (to <= 0)
141                         to = 0;
142                 else
143                         to *= 1000;
144         }
145
146         if (ast_strlen_zero(filename)) 
147                 filename = NULL;
148         if (maxdigitstr) {
149                 maxdigits = atoi(maxdigitstr);
150                 if ((maxdigits<1) || (maxdigits>255)) {
151                         maxdigits = 255;
152                 } else if (option_verbose > 2)
153                         ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %d digits.\n", maxdigits);
154         }
155         if (ast_strlen_zero(varname)) {
156                 ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n");
157                 LOCAL_USER_REMOVE(u);
158                 return -1;
159         }
160         
161         if (chan->_state != AST_STATE_UP) {
162                 if (option_skip) {
163                         /* At the user's option, skip if the line is not up */
164                         pbx_builtin_setvar_helper(chan, varname, "\0");
165                         LOCAL_USER_REMOVE(u);
166                         return 0;
167                 } else if (!option_noanswer) {
168                         /* Otherwise answer unless we're supposed to read while on-hook */
169                         res = ast_answer(chan);
170                 }
171         }
172         if (!res) {
173                 while(tries && !res) {
174                         ast_stopstream(chan);
175                         res = ast_app_getdata(chan, filename, tmp, maxdigits, to);
176                         if (res > -1) {
177                                 pbx_builtin_setvar_helper(chan, varname, tmp);
178                                 if (!ast_strlen_zero(tmp)) {
179                                         if (option_verbose > 2)
180                                                 ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
181                                         tries = 0;
182                                 } else {
183                                         tries--;
184                                         if (option_verbose > 2) {
185                                                 if (tries)
186                                                         ast_verbose(VERBOSE_PREFIX_3 "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
187                                                 else
188                                                         ast_verbose(VERBOSE_PREFIX_3 "User entered nothing.\n");
189                                         }
190                                 }
191                                 res = 0;
192                         } else {
193                                 if (option_verbose > 2)
194                                         ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
195                         }
196                 }
197         }
198         LOCAL_USER_REMOVE(u);
199         return res;
200 }
201
202 int unload_module(void)
203 {
204         int res;
205
206         res = ast_unregister_application(app);
207         
208         STANDARD_HANGUP_LOCALUSERS;
209
210         return res;     
211 }
212
213 int load_module(void)
214 {
215         return ast_register_application(app, read_exec, synopsis, descrip);
216 }
217
218 char *description(void)
219 {
220         return tdesc;
221 }
222
223 int usecount(void)
224 {
225         int res;
226         STANDARD_USECOUNT(res);
227         return res;
228 }
229
230 char *key()
231 {
232         return ASTERISK_GPL_KEY;
233 }