Hello, I have made some modifications to microcom to make it more useful to me. In particular, I needed to send a ^C and a Break to the remote device (Cisco router).
Here are the more detailed changes: . Catch common signals to clean up the lock file and TTY modes. . Allow stdin to not be a TTY so pipes can be used. . Save both TTY settings before changing them to make cleanup easier. . Clear ISIG so that control characters (e.g., ^C, ^Z, ^U, etc) are passed through to the device. Turn off IEXTEN and BRKINT. Enable HUPCL and CREAD. . Set the device communications mode to 8-1-N. . Removed the stdin flush calls at the start and end. I don't think that they are needed. . Removed ignore of SIGINT. If user is a TTY, there won't be a SIGINT because ISIG is now cleared. If user is not a TTY (e.g., a pipe), then SIGINT should stop the program (now that SIGINT is caught). . Send data from the device to the user's stdout rather than the stdin so that the program output can be redirected. . Translate ^@ into a line break. Here's the patch:
diff -ur busybox-1.8.2.orig/miscutils/microcom.c busybox-1.8.2.new/miscutils/microcom.c --- busybox-1.8.2.orig/miscutils/microcom.c 2007-11-09 17:40:53.000000000 -0800 +++ busybox-1.8.2.new/miscutils/microcom.c 2008-01-16 18:44:44.715294000 -0800 @@ -9,19 +9,30 @@ */ #include "libbb.h" +static volatile int gotSig; + +static void +sigCatch(int signo) +{ + gotSig = signo; +} + int microcom_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int microcom_main(int argc, char **argv) { struct pollfd pfd[2]; + int outfd[2]; #define sfd (pfd[1].fd) char *device_lock_file = NULL; const char *s; const char *opt_s = "9600"; unsigned speed; int len; + int usr_is_tty; int exitcode = 1; struct termios tio0, tiosfd, tio; + // Process the command arguments getopt32(argv, "s:", &opt_s); argc -= optind; argv += optind; @@ -29,13 +40,21 @@ bb_show_usage(); speed = xatou(opt_s); - // try to create lock file in /var/lock + // Create the lock file name s = bb_basename(argv[0]); if (!s[0]) { errno = ENODEV; bb_perror_msg_and_die("can't lock device"); } device_lock_file = xasprintf("/var/lock/LCK..%s", s); + + // Orderly exit to remove lock file and restore tty settings + sig_catch(SIGHUP, sigCatch); + sig_catch(SIGINT, sigCatch); + sig_catch(SIGTERM, sigCatch); + sig_catch(SIGPIPE, sigCatch); + + // Acquire the lock file sfd = open(device_lock_file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644); if (sfd < 0) { if (ENABLE_FEATURE_CLEAN_UP) @@ -55,76 +74,101 @@ close(sfd); } - // open device + // Open device, save current tty settings sfd = open(argv[0], O_RDWR); if (sfd < 0) { bb_perror_msg("can't open device"); goto unlock_and_exit; } - - // put stdin to "raw mode", handle one character at a time - tcgetattr(STDIN_FILENO, &tio0); - tio = tio0; - tio.c_lflag &= ~(ICANON|ECHO); - tio.c_iflag &= ~(IXON|ICRNL); - tio.c_oflag &= ~(ONLCR); - tio.c_cc[VMIN] = 1; - tio.c_cc[VTIME] = 0; - if (tcsetattr(STDIN_FILENO, TCSANOW, &tio)) { - bb_perror_msg("can't tcsetattr for %s", "stdin"); + if (tcgetattr(sfd, &tiosfd)) { + bb_perror_msg("can't tcgetattr for %s", "device"); + goto unlock_and_exit; + } + usr_is_tty = isatty(STDIN_FILENO); + if (usr_is_tty && tcgetattr(STDIN_FILENO, &tio0)) { + bb_perror_msg("can't tcgetattr for %s", "stdin"); goto unlock_and_exit; } - /* same thing for modem (plus: set baud rate) - TODO: make CLI option */ - tcgetattr(sfd, &tiosfd); + // Put device in "raw mode", handle one character at a time. + // TODO: make CLI option tio = tiosfd; - tio.c_lflag &= ~(ICANON|ECHO); - tio.c_iflag &= ~(IXON|ICRNL); + tio.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN); + tio.c_iflag &= ~(BRKINT|IXON|ICRNL); tio.c_oflag &= ~(ONLCR); - tio.c_cc[VMIN] = 1; + tio.c_cflag &= ~(CSIZE|CSTOPB|PARENB); + tio.c_cflag |= (CS8|CREAD|HUPCL); // set 8-1-none + tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; - cfsetispeed(&tio, tty_value_to_baud(speed)); + cfsetispeed(&tio, tty_value_to_baud(speed)); // set baudrate cfsetospeed(&tio, tty_value_to_baud(speed)); if (tcsetattr(sfd, TCSANOW, &tio)) { bb_perror_msg("can't tcsetattr for %s", "device"); - goto unlock_and_exit; + goto cleanup_and_exit; } - // disable SIGINT - signal(SIGINT, SIG_IGN); + // Now put the user "raw more" if it's a tty + if (usr_is_tty) { + tio = tio0; + tio.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN); + tio.c_iflag &= ~(BRKINT|IXON|ICRNL); + tio.c_oflag &= ~(ONLCR); + tio.c_cc[VMIN] = 1; + tio.c_cc[VTIME] = 0; + if (tcsetattr(STDIN_FILENO, TCSANOW, &tio)) { + bb_perror_msg("can't tcsetattr for %s", "stdin"); + goto cleanup_and_exit; + } + } - // drain stdin - tcflush(STDIN_FILENO, TCIFLUSH); - printf("connected to '%s' (%d bps), exit with ctrl-X...\r\n", argv[0], speed); + printf("connected to '%s' (%d bps), exit with ctrl-X...\r\n", + argv[0], speed); // main loop: check with poll(), then read/write bytes across + exitcode = 0; + outfd[0] = sfd; + outfd[1] = STDOUT_FILENO; pfd[0].fd = STDIN_FILENO; pfd[0].events = POLLIN; - /*pfd[1].fd = sfd;*/ pfd[1].events = POLLIN; + if (gotSig) + goto cleanup_and_exit; + while (1) { int i; safe_poll(pfd, 2, -1); for (i = 0; i < 2; ++i) { + if (gotSig) + goto cleanup_and_exit; if (pfd[i].revents & POLLIN) { - len = read(pfd[i].fd, bb_common_bufsiz1, COMMON_BUFSIZE); - if (len > 0) { - if (!i && 24 == bb_common_bufsiz1[0]) - goto done; // ^X exits - write(pfd[1-i].fd, bb_common_bufsiz1, len); + char *buf = bb_common_bufsiz1; + if ((len = read(pfd[i].fd, buf, COMMON_BUFSIZE)) <= 0) + goto cleanup_and_exit; + if (!i) { // Process stdin: + again: + if (24 == buf[0]) // ^X exits + goto cleanup_and_exit; + if (0 == buf[0]) { // ^@ sends Break + tcsendbreak(outfd[i], 0); + if (--len <= 0) + continue; + buf++; + goto again; // next byte + } } + if (write(outfd[i], buf, len) != len) + goto cleanup_and_exit; } } } - done: - tcsetattr(sfd, TCSANOW, &tiosfd); - tcsetattr(STDIN_FILENO, TCSANOW, &tio0); - tcflush(STDIN_FILENO, TCIFLUSH); + cleanup_and_exit: + // Restore tty modes + if (usr_is_tty) + tcsetattr(STDIN_FILENO, TCSANOW, &tio0); + tcsetattr(sfd, TCSANOW, &tiosfd); if (ENABLE_FEATURE_CLEAN_UP) close(sfd); - exitcode = 0; - unlock_and_exit: // delete lock file if (device_lock_file) {
_______________________________________________ busybox mailing list busybox@busybox.net http://busybox.net/cgi-bin/mailman/listinfo/busybox