75
75
<option name="n">
76
76
<para>to read digits even if the line is not up.</para>
77
77
</option>
78
+ <option name="t">
79
+ <para>Terminator digit(s) to use for ending input.
80
+ Default is <literal>#</literal>. If you need to read
81
+ the digit <literal>#</literal> literally, you should
82
+ remove or change the terminator character. Multiple
83
+ terminator characters may be specified. If no terminator
84
+ digit is present, input cannot be ended using digits
85
+ and you will need to rely on duration and max digits
86
+ for ending input.</para>
87
+ </option>
78
88
</optionlist>
79
89
</parameter>
80
90
<parameter name="attempts">
@@ -114,12 +124,20 @@ enum read_option_flags {
114
124
OPT_SKIP = (1 << 0 ),
115
125
OPT_INDICATION = (1 << 1 ),
116
126
OPT_NOANSWER = (1 << 2 ),
127
+ OPT_TERMINATOR = (1 << 3 ),
128
+ };
129
+
130
+ enum {
131
+ OPT_ARG_TERMINATOR ,
132
+ /* note: this entry _MUST_ be the last one in the enum */
133
+ OPT_ARG_ARRAY_SIZE ,
117
134
};
118
135
119
136
AST_APP_OPTIONS (read_app_options , {
120
137
AST_APP_OPTION ('s' , OPT_SKIP ),
121
138
AST_APP_OPTION ('i' , OPT_INDICATION ),
122
139
AST_APP_OPTION ('n' , OPT_NOANSWER ),
140
+ AST_APP_OPTION_ARG ('t' , OPT_TERMINATOR , OPT_ARG_TERMINATOR ),
123
141
});
124
142
125
143
static char * app = "Read" ;
@@ -132,9 +150,11 @@ static int read_exec(struct ast_channel *chan, const char *data)
132
150
int tries = 1 , to = 0 , x = 0 ;
133
151
double tosec ;
134
152
char * argcopy = NULL ;
153
+ char * opt_args [OPT_ARG_ARRAY_SIZE ];
135
154
struct ast_tone_zone_sound * ts = NULL ;
136
155
struct ast_flags flags = {0 };
137
156
const char * status = "ERROR" ;
157
+ char * terminator = NULL ; /* use default terminator # by default */
138
158
139
159
AST_DECLARE_APP_ARGS (arglist ,
140
160
AST_APP_ARG (variable );
@@ -156,7 +176,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
156
176
AST_STANDARD_APP_ARGS (arglist , argcopy );
157
177
158
178
if (!ast_strlen_zero (arglist .options )) {
159
- ast_app_parse_options (read_app_options , & flags , NULL , arglist .options );
179
+ ast_app_parse_options (read_app_options , & flags , opt_args , arglist .options );
160
180
}
161
181
162
182
if (!ast_strlen_zero (arglist .attempts )) {
@@ -192,6 +212,13 @@ static int read_exec(struct ast_channel *chan, const char *data)
192
212
ts = ast_get_indication_tone (ast_channel_zone (chan ), arglist .filename );
193
213
}
194
214
}
215
+ if (ast_test_flag (& flags , OPT_TERMINATOR )) {
216
+ if (!ast_strlen_zero (arglist .filename )) {
217
+ terminator = opt_args [OPT_ARG_TERMINATOR ];
218
+ } else {
219
+ terminator = "" ; /* no digit inherently will terminate input */
220
+ }
221
+ }
195
222
if (ast_channel_state (chan ) != AST_STATE_UP ) {
196
223
if (ast_test_flag (& flags , OPT_SKIP )) {
197
224
/* At the user's option, skip if the line is not up */
@@ -223,7 +250,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
223
250
break ;
224
251
}
225
252
tmp [x ++ ] = res ;
226
- if (tmp [x - 1 ] == '#' ) {
253
+ if (strchr ( terminator , tmp [x - 1 ]) ) {
227
254
tmp [x - 1 ] = '\0' ;
228
255
status = "OK" ;
229
256
break ;
@@ -233,7 +260,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
233
260
}
234
261
}
235
262
} else {
236
- res = ast_app_getdata (chan , arglist .filename , tmp , maxdigits , to );
263
+ res = ast_app_getdata_terminator (chan , arglist .filename , tmp , maxdigits , to , terminator );
237
264
if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED )
238
265
status = "OK" ;
239
266
else if (res == AST_GETDATA_TIMEOUT )
0 commit comments