Hello!
This is the first draft of chat applet. No optimization yet!
Please, consider
--
Vladimir
diff -Naur busybox.orig/include/applets.h busybox/include/applets.h
--- busybox.orig/include/applets.h 2008-02-11 11:20:21.000000000 +0300
+++ busybox/include/applets.h 2008-02-11 15:45:49.000000000 +0300
@@ -93,6 +93,7 @@
USE_CAL(APPLET(cal, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_CAT(APPLET_NOFORK(cat, cat, _BB_DIR_BIN, _BB_SUID_NEVER, cat))
USE_CATV(APPLET(catv, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CHAT(APPLET(chat, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_CHATTR(APPLET(chattr, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_CHCON(APPLET(chcon, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_CHGRP(APPLET_NOEXEC(chgrp, chgrp, _BB_DIR_BIN, _BB_SUID_NEVER, chgrp))
diff -Naur busybox.orig/include/usage.h busybox/include/usage.h
--- busybox.orig/include/usage.h 2008-02-11 11:20:21.000000000 +0300
+++ busybox/include/usage.h 2008-02-11 12:40:35.000000000 +0300
@@ -204,6 +204,12 @@
" -e End each line with $\n" \
" -t Show tabs as ^I\n" \
" -v Don't use ^x or M-x escapes"
+
+#define chat_trivial_usage \
+ "[-e] [-E] [-v] [-V] [-t timeout] [-r report-file]\n" \
+ "[-T phone-number] [-U phone-number2] {-f chat-file | chat-script}"
+#define chat_full_usage
+
#define chattr_trivial_usage \
"[-R] [-+=AacDdijsStTu] [-v version] files..."
#define chattr_full_usage \
diff -Naur busybox.orig/miscutils/chat.c busybox/miscutils/chat.c
--- busybox.orig/miscutils/chat.c 1970-01-01 03:00:00.000000000 +0300
+++ busybox/miscutils/chat.c 2008-02-11 18:41:01.000000000 +0300
@@ -0,0 +1,276 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bare bones chat utility
+ * inspired by ppp's chat
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <[EMAIL PROTECTED]>
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+
+#define DEFAULT_CHAT_TIMEOUT 45 * 1000
+
+/* All known arches use small ints for signals */
+static volatile smallint signalled;
+
+static int timeout = DEFAULT_CHAT_TIMEOUT;
+
+static void signal_handler(int signo)
+{
+ signalled = 3 + (SIGALRM == signo);
+}
+
+static llist_t *aborts;
+
+static int chat_expect(char *answer)
+{
+ //bb_error_msg("EXPECT: [%s]", answer);
+
+ // shall we wait for answer?
+ if (!answer || !*answer)
+ return 0;
+
+ // reset input buffer
+ int nbuf = sizeof(bb_common_bufsiz1);
+ char *buf = bb_common_bufsiz1; memset(buf, 0, nbuf--);
+ int i;
+
+ // get answer
+ struct pollfd pfd;
+ pfd.fd = STDIN_FILENO;
+ pfd.events = POLLIN;
+ while (!signalled && safe_poll(&pfd, 1, timeout) > 0) {
+ llist_t *l;
+ // read next char(s) from device
+ if (!(pfd.revents & POLLIN))
+ break;
+ if (safe_read(STDIN_FILENO, buf, 1) > 0) {
+ buf++;
+ if (!--nbuf) {
+ bb_error_msg("LINE TOO LONG");
+ return 2;
+ }
+ }
+ // TODO: escape substitutions in received answer!!!
+ // abort matched?
+ for (l = aborts, i = 5; l; l = l->link, ++i)
+ if (strstr(bb_common_bufsiz1, l->data)) {
+ bb_error_msg("ABORTED: [%s]", l->data);
+ return i;
+ }
+ // answer matched?
+ if (strstr(bb_common_bufsiz1, answer)) {
+ // match found!
+ //if (opts & OPT_v) {
+ // bb_error_msg("GOT: [%s]", bb_common_bufsiz1);
+ //}
+ return 0;
+ }
+ }
+
+ // answer timed out or invalid answer received
+ bb_error_msg("FAILED: [%s]", bb_common_bufsiz1);
+ return 4;
+}
+
+//static void chat_send(char *s, int timeout)
+static void chat_send(char *s)
+{
+ char *data = NULL;
+ int cr = 1;
+
+// bb_error_msg("SEND: [%s]", s);
+
+ if ('@' == s[0]) {
+ // skip the @ and any following white-space
+ trim(++s);
+ s = data = xmalloc_open_read_close(s, NULL);
+ }
+
+// if (opts & OPT_v) {
+// bb_error_msg("send (%s)", s);
+// }
+
+ alarm(timeout);
+ while (*s) {
+ // do we need special processing?
+ if ('\\' == *s) {
+ char c = *++s;
+ if (c) {
+ if ('d' == c) {
+ sleep(1);
+ } else if ('p' == c) {
+ usleep(100000);
+ } else if ('K' == c) {
+ tcsendbreak(STDIN_FILENO, 0);
+ } else {
+ if ('r' == c) {
+ c = '\r';
+ } else if ('n' == c) {
+ c = '\n';
+ } else if ('s' == c) {
+ c = ' ';
+ } else if ('t' == c) {
+ c = '\t';
+ } else if ('\\' == c) {
+ c = '\\';
+ } else if ('N' == c) {
+ c = '\0';
+ } else if ('b' == c) {
+ c = '\b';
+ } else if ('c' == c) {
+ cr = 0;
+ continue;
+ } else if (isdigit(c)) {
+ char *e;
+ c = strtoul(s, &e, 8);
+ if (!errno)
+ s = e-1;
+ else ; //???
+ }
+ xwrite(STDOUT_FILENO, &c, 1);
+ }
+ }
+ } else if ('^' == *s) {
+ char c = *++s-'@';
+ xwrite(STDOUT_FILENO, &c, 1);
+ } else {
+ xwrite(STDOUT_FILENO, s, 1);
+ }
+ s++;
+ }
+ if (cr)
+ xwrite(STDOUT_FILENO, "\r", 1);
+ alarm(0);
+
+ if (data)
+ free(data);
+}
+
+int chat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int chat_main(int argc, char **argv)
+{
+ struct termios tio0, tio;
+ enum {
+ OPT_e = 1 << 0, // echo
+ OPT_E = 1 << 1, // use env IGNORED
+ OPT_v = 1 << 2, // verbose IGNORED
+ OPT_V = 1 << 3, // verbose2 IGNORED
+ OPT_s = 1 << 4, // to_stderr IGNORED
+ OPT_S = 1 << 5, // no syslog IGNORED
+ OPT_f = 1 << 6, // script file
+ OPT_t = 1 << 7, // timeout
+ OPT_r = 1 << 8, // report IGNORED
+ OPT_T = 1 << 9, // phone 1 IGNORED
+ OPT_U = 1 << 10, // phone 2 IGNORED
+ };
+
+ enum {
+ DIR_HANGUP = 0,
+ DIR_ABORT,
+ DIR_CLR_ABORT,
+ DIR_REPORT,
+ DIR_CLR_REPORT,
+ DIR_TIMEOUT,
+ DIR_ECHO,
+ DIR_SAY,
+ };
+
+ // fetch options
+ unsigned opts;
+ char *file, *dummy;
+ opt_complementary = "t+";
+ opts = getopt32(argv, "eEvVsSf:t:r:T:U:", &file, &timeout, &dummy, &dummy, &dummy);
+ // process external script
+ if (opts & OPT_f) {
+ // read script
+// char *script = xmalloc_open_read_close(file, NULL);
+ // parse script into argv?
+ // or may be rerun chat via execlp()?
+ //run_applet_and_exit(applet_name, argv);
+ // we never return from here...
+ }
+// argc -= optind;
+ argv += optind;
+
+ // setup signals
+ sig_catch(SIGHUP, signal_handler);
+ sig_catch(SIGINT, signal_handler);
+ sig_catch(SIGTERM, signal_handler);
+ sig_catch(SIGPIPE, signal_handler);
+
+ // put stdin to "raw mode" (if stdin is a TTY),
+ // handle one character at a time
+ tcgetattr(STDIN_FILENO, &tio);
+ tio0 = tio;
+ cfmakeraw(&tio);
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &tio))
+ bb_perror_msg_and_die("can't tcsetattr for STDIN");
+
+ // handle chat pairs
+ while (*argv) {
+// bb_error_msg("PARAM: [%s]", *argv);
+ // directive given? process it
+ int key = index_in_strings(
+ "HANGUP\0ABORT\0CLR_ABORT\0REPORT\0CLR_REPORT\0TIMEOUT\0ECHO\0SAY\0",
+ *argv
+ );
+ if (key >= 0) {
+ char *arg = *++argv;
+ bool onoff = strcmp("OFF", arg);
+ // bb_error_msg("DIRECTIVE: [%d][%s]", key, arg);
+ if (DIR_HANGUP == key) {
+ // turn SIGHUP on/off
+ sig_catch(SIGHUP, onoff ? signal_handler : SIG_IGN);
+ } else if (DIR_ABORT == key) {
+ // set abort on string
+ llist_add_to_end(&aborts, arg);
+ if (opts & OPT_v)
+ bb_error_msg("abort on (%s)", arg);
+ } else if (DIR_CLR_ABORT == key) {
+ // clear previously set abort string
+ for (llist_t *l = aborts; l; l = l->link) {
+ if (!strcmp(l->data, arg)) {
+ llist_unlink(&aborts, l);
+ if (opts & OPT_v)
+ bb_error_msg("clear abort on (%s)", arg);
+ break;
+ }
+ }
+/* } else if (DIR_REPORT == key) {
+ // IGNORED
+ } else if (DIR_CLR_REPORT == key) {
+ // IGNORED
+*/ } else if (DIR_TIMEOUT == key) {
+ // set new timeout
+ timeout = atoi(arg) * 1000;
+ if (timeout <= 0)
+ timeout = DEFAULT_CHAT_TIMEOUT;
+ if (opts & OPT_v)
+ bb_error_msg("timeout set to %u milliseconds", timeout);
+/* } else if (DIR_ECHO == key) {
+ // turn echo on/off
+ if (onoff)
+ opts |= OPT_e;
+ else
+ opts &= ~OPT_e;
+*/ } else if (DIR_SAY == key) {
+ // just print argument
+ bb_error_msg(arg);
+ }
+ argv++;
+ // wait for specific reply
+ } else {
+ if ((signalled=chat_expect(*argv++)))
+ break;
+ if (*argv)
+ // send command
+ chat_send(*argv++);
+ }
+ }
+
+ tcsetattr(STDIN_FILENO, TCSANOW, &tio0);
+
+ return signalled;
+}
diff -Naur busybox.orig/miscutils/Config.in busybox/miscutils/Config.in
--- busybox.orig/miscutils/Config.in 2008-02-11 11:20:20.000000000 +0300
+++ busybox/miscutils/Config.in 2008-02-11 11:22:28.000000000 +0300
@@ -19,6 +19,12 @@
The bbconfig applet will print the config file with which
busybox was built.
+config CHAT
+ bool "chat"
+ default n
+ help
+ Simple chat utility.
+
config CHRT
bool "chrt"
default n
diff -Naur busybox.orig/miscutils/Kbuild busybox/miscutils/Kbuild
--- busybox.orig/miscutils/Kbuild 2008-02-11 11:20:20.000000000 +0300
+++ busybox/miscutils/Kbuild 2008-02-11 15:46:03.000000000 +0300
@@ -7,6 +7,7 @@
lib-y:=
lib-$(CONFIG_ADJTIMEX) += adjtimex.o
lib-$(CONFIG_BBCONFIG) += bbconfig.o
+lib-$(CONFIG_CHAT) += chat.o
lib-$(CONFIG_CHRT) += chrt.o
lib-$(CONFIG_CROND) += crond.o
lib-$(CONFIG_CRONTAB) += crontab.o
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox