aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-03-16 23:06:23 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-03-16 23:06:23 +0000
commit99d71da1cf7d9df8d4153cd109742f6551339d94 (patch)
tree4d7e50f3b8852af558c8129871e7d51750a99a66
parent074c9036b2e656eda086e71800552e1054a4d648 (diff)
downloadbusybox-w32-99d71da1cf7d9df8d4153cd109742f6551339d94.tar.gz
busybox-w32-99d71da1cf7d9df8d4153cd109742f6551339d94.tar.bz2
busybox-w32-99d71da1cf7d9df8d4153cd109742f6551339d94.zip
chat: update by Vladimir
1) to treat timeout more correctly (timeout affects whole send command duration, not a single char); 2) to recognize RECORD directive. function old new delta chat_main 1246 1359 +113 exitcode 1 - -1
-rw-r--r--miscutils/chat.c97
1 files changed, 44 insertions, 53 deletions
diff --git a/miscutils/chat.c b/miscutils/chat.c
index d550c7c90..3ffd7b228 100644
--- a/miscutils/chat.c
+++ b/miscutils/chat.c
@@ -9,16 +9,6 @@
9 */ 9 */
10#include "libbb.h" 10#include "libbb.h"
11 11
12/*
13#define ENABLE_FEATURE_CHAT_NOFAIL 1 // +126 bytes
14#define ENABLE_FEATURE_CHAT_TTY_HIFI 0 // + 70 bytes
15#define ENABLE_FEATURE_CHAT_IMPLICIT_CR 1 // + 44 bytes
16#define ENABLE_FEATURE_CHAT_SEND_ESCAPES 0 // +103 bytes
17#define ENABLE_FEATURE_CHAT_VAR_ABORT_LEN 0 // + 70 bytes
18#define ENABLE_FEATURE_CHAT_CLR_ABORT 0 // +113 bytes
19#define ENABLE_FEATURE_CHAT_SWALLOW_OPTS 0 // + 23 bytes
20*/
21
22// default timeout: 45 sec 12// default timeout: 45 sec
23#define DEFAULT_CHAT_TIMEOUT 45*1000 13#define DEFAULT_CHAT_TIMEOUT 45*1000
24// max length of "abort string", 14// max length of "abort string",
@@ -37,8 +27,7 @@ enum {
37}; 27};
38 28
39// exit code 29// exit code
40// N.B> 10 bytes for volatile. Why all these signals?! 30#define exitcode bb_got_signal
41static /*volatile*/ smallint exitcode;
42 31
43// trap for critical signals 32// trap for critical signals
44static void signal_handler(UNUSED_PARAM int signo) 33static void signal_handler(UNUSED_PARAM int signo)
@@ -101,13 +90,10 @@ static size_t unescape(char *s, int *nocr)
101 return p - start; 90 return p - start;
102} 91}
103 92
104
105int chat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 93int chat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
106int chat_main(int argc UNUSED_PARAM, char **argv) 94int chat_main(int argc UNUSED_PARAM, char **argv)
107{ 95{
108// should we dump device output? to what fd? by default no. 96 int record_fd = -1;
109// this can be controlled later via ECHO {ON|OFF} chat directive
110// int echo_fd;
111 bool echo = 0; 97 bool echo = 0;
112 // collection of device replies which cause unconditional termination 98 // collection of device replies which cause unconditional termination
113 llist_t *aborts = NULL; 99 llist_t *aborts = NULL;
@@ -132,6 +118,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
132 DIR_TIMEOUT, 118 DIR_TIMEOUT,
133 DIR_ECHO, 119 DIR_ECHO,
134 DIR_SAY, 120 DIR_SAY,
121 DIR_RECORD,
135 }; 122 };
136 123
137 // make x* functions fail with correct exitcode 124 // make x* functions fail with correct exitcode
@@ -166,14 +153,14 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
166#if ENABLE_FEATURE_CHAT_CLR_ABORT 153#if ENABLE_FEATURE_CHAT_CLR_ABORT
167 "CLR_ABORT\0" 154 "CLR_ABORT\0"
168#endif 155#endif
169 "TIMEOUT\0" "ECHO\0" "SAY\0" 156 "TIMEOUT\0" "ECHO\0" "SAY\0" "RECORD\0"
170 , *argv 157 , *argv
171 ); 158 );
172 if (key >= 0) { 159 if (key >= 0) {
173 // cache directive value 160 // cache directive value
174 char *arg = *++argv; 161 char *arg = *++argv;
175 // ON -> 1, anything else -> 0 162 // OFF -> 0, anything else -> 1
176 bool onoff = !strcmp("ON", arg); 163 bool onoff = (0 != strcmp("OFF", arg));
177 // process directive 164 // process directive
178 if (DIR_HANGUP == key) { 165 if (DIR_HANGUP == key) {
179 // turn SIGHUP on/off 166 // turn SIGHUP on/off
@@ -217,14 +204,20 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
217 timeout = DEFAULT_CHAT_TIMEOUT; 204 timeout = DEFAULT_CHAT_TIMEOUT;
218 } else if (DIR_ECHO == key) { 205 } else if (DIR_ECHO == key) {
219 // turn echo on/off 206 // turn echo on/off
220 // N.B. echo means dumping output 207 // N.B. echo means dumping device input/output to stderr
221 // from stdin (device) to stderr
222 echo = onoff; 208 echo = onoff;
223//TODO? echo_fd = onoff * STDERR_FILENO; 209 } else if (DIR_RECORD == key) {
224//TODO? echo_fd = xopen(arg, O_WRONLY|O_CREAT|O_TRUNC); 210 // turn record on/off
211 // N.B. record means dumping device input to a file
212 // close previous record_fd
213 if (record_fd > 0)
214 close(record_fd);
215 // N.B. do we have to die here on open error?
216 record_fd = (onoff) ? xopen(arg, O_WRONLY|O_CREAT|O_TRUNC) : -1;
225 } else if (DIR_SAY == key) { 217 } else if (DIR_SAY == key) {
226 // just print argument verbatim 218 // just print argument verbatim
227 fprintf(stderr, arg); 219 // TODO: should we use full_write() to avoid unistd/stdio conflict?
220 bb_error_msg("%s", arg);
228 } 221 }
229 // next, please! 222 // next, please!
230 argv++; 223 argv++;
@@ -288,12 +281,18 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
288 281
289 // read next char from device 282 // read next char from device
290 if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) { 283 if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) {
291 // dump device output if ECHO ON or RECORD fname 284 // dump device input if RECORD fname
292//TODO? if (echo_fd > 0) { 285 if (record_fd > 0) {
293//TODO? full_write(echo_fd, buf+buf_len, 1); 286 full_write(record_fd, buf+buf_len, 1);
294//TODO? } 287 }
295 if (echo > 0) 288 // dump device input if ECHO ON
289 if (echo > 0) {
290// if (buf[buf_len] < ' ') {
291// full_write(STDERR_FILENO, "^", 1);
292// buf[buf_len] += '@';
293// }
296 full_write(STDERR_FILENO, buf+buf_len, 1); 294 full_write(STDERR_FILENO, buf+buf_len, 1);
295 }
297 buf_len++; 296 buf_len++;
298 // move input frame if we've reached higher bound 297 // move input frame if we've reached higher bound
299 if (buf_len > COMMON_BUFSIZE) { 298 if (buf_len > COMMON_BUFSIZE) {
@@ -320,7 +319,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
320 if (delta >= 0 && !memcmp(buf+delta, expect, expect_len)) 319 if (delta >= 0 && !memcmp(buf+delta, expect, expect_len))
321 goto expect_done; 320 goto expect_done;
322#undef buf 321#undef buf
323 } 322 } /* while (have data) */
324 323
325 // device timed out or unexpected reply received 324 // device timed out or unexpected reply received
326 exitcode = ERR_TIMEOUT; 325 exitcode = ERR_TIMEOUT;
@@ -365,21 +364,18 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
365 trim(++buf); 364 trim(++buf);
366 buf = loaded = xmalloc_xopen_read_close(buf, NULL); 365 buf = loaded = xmalloc_xopen_read_close(buf, NULL);
367 } 366 }
368
369 // expand escape sequences in command 367 // expand escape sequences in command
370 len = unescape(buf, &nocr); 368 len = unescape(buf, &nocr);
371 369
372 // send command 370 // send command
373#if ENABLE_FEATURE_CHAT_SEND_ESCAPES 371 alarm(timeout);
374 pfd.fd = STDOUT_FILENO; 372 pfd.fd = STDOUT_FILENO;
375 pfd.events = POLLOUT; 373 pfd.events = POLLOUT;
376 while (len && !exitcode 374 while (len && !exitcode
377 && poll(&pfd, 1, timeout) > 0 375 && poll(&pfd, 1, -1) > 0
378 && (pfd.revents & POLLOUT) 376 && (pfd.revents & POLLOUT)
379 ) { 377 ) {
380 // ugly! ugly! ugly! 378#if ENABLE_FEATURE_CHAT_SEND_ESCAPES
381 // gotta send char by char to achieve this!
382 // Brrr...
383 // "\\d" means 1 sec delay, "\\p" means 0.01 sec delay 379 // "\\d" means 1 sec delay, "\\p" means 0.01 sec delay
384 // "\\K" means send BREAK 380 // "\\K" means send BREAK
385 char c = *buf; 381 char c = *buf;
@@ -389,31 +385,28 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
389 sleep(1); 385 sleep(1);
390 len--; 386 len--;
391 continue; 387 continue;
392 } else if ('p' == c) { 388 }
389 if ('p' == c) {
393 usleep(10000); 390 usleep(10000);
394 len--; 391 len--;
395 continue; 392 continue;
396 } else if ('K' == c) { 393 }
394 if ('K' == c) {
397 tcsendbreak(STDOUT_FILENO, 0); 395 tcsendbreak(STDOUT_FILENO, 0);
398 len--; 396 len--;
399 continue; 397 continue;
400 } else {
401 buf--;
402 } 398 }
399 buf--;
403 } 400 }
404 if (safe_write(STDOUT_FILENO, buf, 1) > 0) { 401 if (safe_write(STDOUT_FILENO, buf, 1) != 1)
405 len--;
406 buf++;
407 } else
408 break; 402 break;
409 } 403 len--;
404 buf++;
410#else 405#else
411// if (len) {
412 alarm(timeout);
413 len -= full_write(STDOUT_FILENO, buf, len); 406 len -= full_write(STDOUT_FILENO, buf, len);
414 alarm(0);
415// }
416#endif 407#endif
408 } /* while (can write) */
409 alarm(0);
417 410
418 // report I/O error if there still exists at least one non-sent char 411 // report I/O error if there still exists at least one non-sent char
419 if (len) 412 if (len)
@@ -427,14 +420,12 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
427 else if (!nocr) 420 else if (!nocr)
428 xwrite(STDOUT_FILENO, "\r", 1); 421 xwrite(STDOUT_FILENO, "\r", 1);
429#endif 422#endif
430
431 // bail out unless we sent command successfully 423 // bail out unless we sent command successfully
432 if (exitcode) 424 if (exitcode)
433 break; 425 break;
434 426 } /* if (*argv) */
435 }
436 } 427 }
437 } 428 } /* while (*argv) */
438 429
439#if ENABLE_FEATURE_CHAT_TTY_HIFI 430#if ENABLE_FEATURE_CHAT_TTY_HIFI
440 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0); 431 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);