mirror of
https://github.com/sheumann/hush.git
synced 2024-10-11 10:23:41 +00:00
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
This commit is contained in:
parent
074c9036b2
commit
99d71da1cf
@ -9,16 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
/*
|
|
||||||
#define ENABLE_FEATURE_CHAT_NOFAIL 1 // +126 bytes
|
|
||||||
#define ENABLE_FEATURE_CHAT_TTY_HIFI 0 // + 70 bytes
|
|
||||||
#define ENABLE_FEATURE_CHAT_IMPLICIT_CR 1 // + 44 bytes
|
|
||||||
#define ENABLE_FEATURE_CHAT_SEND_ESCAPES 0 // +103 bytes
|
|
||||||
#define ENABLE_FEATURE_CHAT_VAR_ABORT_LEN 0 // + 70 bytes
|
|
||||||
#define ENABLE_FEATURE_CHAT_CLR_ABORT 0 // +113 bytes
|
|
||||||
#define ENABLE_FEATURE_CHAT_SWALLOW_OPTS 0 // + 23 bytes
|
|
||||||
*/
|
|
||||||
|
|
||||||
// default timeout: 45 sec
|
// default timeout: 45 sec
|
||||||
#define DEFAULT_CHAT_TIMEOUT 45*1000
|
#define DEFAULT_CHAT_TIMEOUT 45*1000
|
||||||
// max length of "abort string",
|
// max length of "abort string",
|
||||||
@ -37,8 +27,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// exit code
|
// exit code
|
||||||
// N.B> 10 bytes for volatile. Why all these signals?!
|
#define exitcode bb_got_signal
|
||||||
static /*volatile*/ smallint exitcode;
|
|
||||||
|
|
||||||
// trap for critical signals
|
// trap for critical signals
|
||||||
static void signal_handler(UNUSED_PARAM int signo)
|
static void signal_handler(UNUSED_PARAM int signo)
|
||||||
@ -101,13 +90,10 @@ static size_t unescape(char *s, int *nocr)
|
|||||||
return p - start;
|
return p - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int chat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int chat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int chat_main(int argc UNUSED_PARAM, char **argv)
|
int chat_main(int argc UNUSED_PARAM, char **argv)
|
||||||
{
|
{
|
||||||
// should we dump device output? to what fd? by default no.
|
int record_fd = -1;
|
||||||
// this can be controlled later via ECHO {ON|OFF} chat directive
|
|
||||||
// int echo_fd;
|
|
||||||
bool echo = 0;
|
bool echo = 0;
|
||||||
// collection of device replies which cause unconditional termination
|
// collection of device replies which cause unconditional termination
|
||||||
llist_t *aborts = NULL;
|
llist_t *aborts = NULL;
|
||||||
@ -132,6 +118,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
DIR_TIMEOUT,
|
DIR_TIMEOUT,
|
||||||
DIR_ECHO,
|
DIR_ECHO,
|
||||||
DIR_SAY,
|
DIR_SAY,
|
||||||
|
DIR_RECORD,
|
||||||
};
|
};
|
||||||
|
|
||||||
// make x* functions fail with correct exitcode
|
// make x* functions fail with correct exitcode
|
||||||
@ -166,14 +153,14 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
#if ENABLE_FEATURE_CHAT_CLR_ABORT
|
#if ENABLE_FEATURE_CHAT_CLR_ABORT
|
||||||
"CLR_ABORT\0"
|
"CLR_ABORT\0"
|
||||||
#endif
|
#endif
|
||||||
"TIMEOUT\0" "ECHO\0" "SAY\0"
|
"TIMEOUT\0" "ECHO\0" "SAY\0" "RECORD\0"
|
||||||
, *argv
|
, *argv
|
||||||
);
|
);
|
||||||
if (key >= 0) {
|
if (key >= 0) {
|
||||||
// cache directive value
|
// cache directive value
|
||||||
char *arg = *++argv;
|
char *arg = *++argv;
|
||||||
// ON -> 1, anything else -> 0
|
// OFF -> 0, anything else -> 1
|
||||||
bool onoff = !strcmp("ON", arg);
|
bool onoff = (0 != strcmp("OFF", arg));
|
||||||
// process directive
|
// process directive
|
||||||
if (DIR_HANGUP == key) {
|
if (DIR_HANGUP == key) {
|
||||||
// turn SIGHUP on/off
|
// turn SIGHUP on/off
|
||||||
@ -217,14 +204,20 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
timeout = DEFAULT_CHAT_TIMEOUT;
|
timeout = DEFAULT_CHAT_TIMEOUT;
|
||||||
} else if (DIR_ECHO == key) {
|
} else if (DIR_ECHO == key) {
|
||||||
// turn echo on/off
|
// turn echo on/off
|
||||||
// N.B. echo means dumping output
|
// N.B. echo means dumping device input/output to stderr
|
||||||
// from stdin (device) to stderr
|
|
||||||
echo = onoff;
|
echo = onoff;
|
||||||
//TODO? echo_fd = onoff * STDERR_FILENO;
|
} else if (DIR_RECORD == key) {
|
||||||
//TODO? echo_fd = xopen(arg, O_WRONLY|O_CREAT|O_TRUNC);
|
// turn record on/off
|
||||||
|
// N.B. record means dumping device input to a file
|
||||||
|
// close previous record_fd
|
||||||
|
if (record_fd > 0)
|
||||||
|
close(record_fd);
|
||||||
|
// N.B. do we have to die here on open error?
|
||||||
|
record_fd = (onoff) ? xopen(arg, O_WRONLY|O_CREAT|O_TRUNC) : -1;
|
||||||
} else if (DIR_SAY == key) {
|
} else if (DIR_SAY == key) {
|
||||||
// just print argument verbatim
|
// just print argument verbatim
|
||||||
fprintf(stderr, arg);
|
// TODO: should we use full_write() to avoid unistd/stdio conflict?
|
||||||
|
bb_error_msg("%s", arg);
|
||||||
}
|
}
|
||||||
// next, please!
|
// next, please!
|
||||||
argv++;
|
argv++;
|
||||||
@ -288,12 +281,18 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
|
|
||||||
// read next char from device
|
// read next char from device
|
||||||
if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) {
|
if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) {
|
||||||
// dump device output if ECHO ON or RECORD fname
|
// dump device input if RECORD fname
|
||||||
//TODO? if (echo_fd > 0) {
|
if (record_fd > 0) {
|
||||||
//TODO? full_write(echo_fd, buf+buf_len, 1);
|
full_write(record_fd, buf+buf_len, 1);
|
||||||
//TODO? }
|
}
|
||||||
if (echo > 0)
|
// dump device input if ECHO ON
|
||||||
|
if (echo > 0) {
|
||||||
|
// if (buf[buf_len] < ' ') {
|
||||||
|
// full_write(STDERR_FILENO, "^", 1);
|
||||||
|
// buf[buf_len] += '@';
|
||||||
|
// }
|
||||||
full_write(STDERR_FILENO, buf+buf_len, 1);
|
full_write(STDERR_FILENO, buf+buf_len, 1);
|
||||||
|
}
|
||||||
buf_len++;
|
buf_len++;
|
||||||
// move input frame if we've reached higher bound
|
// move input frame if we've reached higher bound
|
||||||
if (buf_len > COMMON_BUFSIZE) {
|
if (buf_len > COMMON_BUFSIZE) {
|
||||||
@ -320,7 +319,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (delta >= 0 && !memcmp(buf+delta, expect, expect_len))
|
if (delta >= 0 && !memcmp(buf+delta, expect, expect_len))
|
||||||
goto expect_done;
|
goto expect_done;
|
||||||
#undef buf
|
#undef buf
|
||||||
}
|
} /* while (have data) */
|
||||||
|
|
||||||
// device timed out or unexpected reply received
|
// device timed out or unexpected reply received
|
||||||
exitcode = ERR_TIMEOUT;
|
exitcode = ERR_TIMEOUT;
|
||||||
@ -365,21 +364,18 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
trim(++buf);
|
trim(++buf);
|
||||||
buf = loaded = xmalloc_xopen_read_close(buf, NULL);
|
buf = loaded = xmalloc_xopen_read_close(buf, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand escape sequences in command
|
// expand escape sequences in command
|
||||||
len = unescape(buf, &nocr);
|
len = unescape(buf, &nocr);
|
||||||
|
|
||||||
// send command
|
// send command
|
||||||
#if ENABLE_FEATURE_CHAT_SEND_ESCAPES
|
alarm(timeout);
|
||||||
pfd.fd = STDOUT_FILENO;
|
pfd.fd = STDOUT_FILENO;
|
||||||
pfd.events = POLLOUT;
|
pfd.events = POLLOUT;
|
||||||
while (len && !exitcode
|
while (len && !exitcode
|
||||||
&& poll(&pfd, 1, timeout) > 0
|
&& poll(&pfd, 1, -1) > 0
|
||||||
&& (pfd.revents & POLLOUT)
|
&& (pfd.revents & POLLOUT)
|
||||||
) {
|
) {
|
||||||
// ugly! ugly! ugly!
|
#if ENABLE_FEATURE_CHAT_SEND_ESCAPES
|
||||||
// gotta send char by char to achieve this!
|
|
||||||
// Brrr...
|
|
||||||
// "\\d" means 1 sec delay, "\\p" means 0.01 sec delay
|
// "\\d" means 1 sec delay, "\\p" means 0.01 sec delay
|
||||||
// "\\K" means send BREAK
|
// "\\K" means send BREAK
|
||||||
char c = *buf;
|
char c = *buf;
|
||||||
@ -389,31 +385,28 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
sleep(1);
|
sleep(1);
|
||||||
len--;
|
len--;
|
||||||
continue;
|
continue;
|
||||||
} else if ('p' == c) {
|
}
|
||||||
|
if ('p' == c) {
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
len--;
|
len--;
|
||||||
continue;
|
continue;
|
||||||
} else if ('K' == c) {
|
}
|
||||||
|
if ('K' == c) {
|
||||||
tcsendbreak(STDOUT_FILENO, 0);
|
tcsendbreak(STDOUT_FILENO, 0);
|
||||||
len--;
|
len--;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
buf--;
|
|
||||||
}
|
}
|
||||||
|
buf--;
|
||||||
}
|
}
|
||||||
if (safe_write(STDOUT_FILENO, buf, 1) > 0) {
|
if (safe_write(STDOUT_FILENO, buf, 1) != 1)
|
||||||
len--;
|
|
||||||
buf++;
|
|
||||||
} else
|
|
||||||
break;
|
break;
|
||||||
}
|
len--;
|
||||||
|
buf++;
|
||||||
#else
|
#else
|
||||||
// if (len) {
|
|
||||||
alarm(timeout);
|
|
||||||
len -= full_write(STDOUT_FILENO, buf, len);
|
len -= full_write(STDOUT_FILENO, buf, len);
|
||||||
alarm(0);
|
|
||||||
// }
|
|
||||||
#endif
|
#endif
|
||||||
|
} /* while (can write) */
|
||||||
|
alarm(0);
|
||||||
|
|
||||||
// report I/O error if there still exists at least one non-sent char
|
// report I/O error if there still exists at least one non-sent char
|
||||||
if (len)
|
if (len)
|
||||||
@ -427,14 +420,12 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
else if (!nocr)
|
else if (!nocr)
|
||||||
xwrite(STDOUT_FILENO, "\r", 1);
|
xwrite(STDOUT_FILENO, "\r", 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// bail out unless we sent command successfully
|
// bail out unless we sent command successfully
|
||||||
if (exitcode)
|
if (exitcode)
|
||||||
break;
|
break;
|
||||||
|
} /* if (*argv) */
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} /* while (*argv) */
|
||||||
|
|
||||||
#if ENABLE_FEATURE_CHAT_TTY_HIFI
|
#if ENABLE_FEATURE_CHAT_TTY_HIFI
|
||||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);
|
||||||
|
Loading…
Reference in New Issue
Block a user