fdisk: placate warning of strncpy not copying NUL byte
[oweals/busybox.git] / miscutils / microcom.c
index ac3e5514f3a07b690039b54bbe057ec63f65bf72..fa090057e72ca4ea2342957923c79287d77309f6 100644 (file)
@@ -5,29 +5,39 @@
  *
  * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
  *
- * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2, see file LICENSE in this source tree.
  */
-#include "libbb.h"
-
-/* All known arches use small ints for signals */
-static volatile smallint signalled;
+//config:config MICROCOM
+//config:      bool "microcom (5.6 kb)"
+//config:      default y
+//config:      help
+//config:      The poor man's minicom utility for chatting with serial port devices.
+
+//applet:IF_MICROCOM(APPLET(microcom, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_MICROCOM) += microcom.o
+
+//usage:#define microcom_trivial_usage
+//usage:       "[-d DELAY] [-t TIMEOUT] [-s SPEED] [-X] TTY"
+//usage:#define microcom_full_usage "\n\n"
+//usage:       "Copy bytes for stdin to TTY and from TTY to stdout\n"
+//usage:     "\n       -d      Wait up to DELAY ms for TTY output before sending every"
+//usage:     "\n               next byte to it"
+//usage:     "\n       -t      Exit if both stdin and TTY are silent for TIMEOUT ms"
+//usage:     "\n       -s      Set serial line to SPEED"
+//usage:     "\n       -X      Disable special meaning of NUL and Ctrl-X from stdin"
 
-static void signal_handler(int signo)
-{
-       signalled = signo;
-}
+#include "libbb.h"
+#include "common_bufsiz.h"
 
 // set raw tty mode
 static void xget1(int fd, struct termios *t, struct termios *oldt)
 {
-       tcgetattr(fd, oldt);
-       *t = *oldt;
-       cfmakeraw(t);
-//     t->c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
-//     t->c_iflag &= ~(BRKINT|IXON|ICRNL);
-//     t->c_oflag &= ~(ONLCR);
-//     t->c_cc[VMIN]  = 1;
-//     t->c_cc[VTIME] = 0;
+       get_termios_and_make_raw(fd, t, oldt, 0
+               | TERMIOS_CLEAR_ISIG /* ^C is ASCII char 3, not "interrupt me!" */
+               | TERMIOS_RAW_INPUT /* pass all chars verbatim, no special handling or translating CR->NL */
+               | TERMIOS_RAW_CRNL  /* dont convert NL<->CR on output too */
+       );
 }
 
 static int xset1(int fd, struct termios *tio, const char *device)
@@ -60,8 +70,9 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
        unsigned opts;
 
        // fetch options
-       opt_complementary = "=1:s+:d+:t+"; // exactly one arg, numeric options
-       opts = getopt32(argv, "Xs:d:t:", &speed, &delay, &timeout);
+       opts = getopt32(argv, "^" "Xs:+d:+t:+" "\0" "=1",
+                               &speed, &delay, &timeout
+       );
 //     argc -= optind;
        argv += optind;
 
@@ -72,7 +83,7 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
        if (sfd < 0) {
                // device already locked -> bail out
                if (errno == EEXIST)
-                       bb_perror_msg_and_die("can't create %s", device_lock_file);
+                       bb_perror_msg_and_die("can't create '%s'", device_lock_file);
                // can't create lock -> don't care
                if (ENABLE_FEATURE_CLEAN_UP)
                        free(device_lock_file);
@@ -91,16 +102,16 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
                + (1 << SIGINT)
                + (1 << SIGTERM)
                + (1 << SIGPIPE)
-               , signal_handler);
+               , record_signo);
 
        // error exit code if we fail to open the device
-       signalled = 1;
+       bb_got_signal = 1;
 
        // open device
        sfd = open_or_warn(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK);
        if (sfd < 0)
                goto done;
-       fcntl(sfd, F_SETFL, 0);
+       fcntl(sfd, F_SETFL, O_RDWR);
 
        // put device to "raw mode"
        xget1(sfd, &tio, &tiosfd);
@@ -123,9 +134,10 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
        pfd[1].fd = STDIN_FILENO;
        pfd[1].events = POLLIN;
 
-       signalled = 0;
+       bb_got_signal = 0;
        nfd = 2;
-       while (!signalled && safe_poll(pfd, nfd, timeout) > 0) {
+       // Not safe_poll: we want to exit on signal
+       while (!bb_got_signal && poll(pfd, nfd, timeout) > 0) {
                if (nfd > 1 && pfd[1].revents) {
                        char c;
                        // read from stdin -> write to device
@@ -151,15 +163,16 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
 skip_write: ;
                }
                if (pfd[0].revents) {
-#define iobuf bb_common_bufsiz1
                        ssize_t len;
+#define iobuf bb_common_bufsiz1
+                       setup_common_bufsiz();
                        // read from device -> write to stdout
-                       len = safe_read(sfd, iobuf, sizeof(iobuf));
+                       len = safe_read(sfd, iobuf, COMMON_BUFSIZE);
                        if (len > 0)
                                full_write(STDOUT_FILENO, iobuf, len);
                        else {
                                // EOF/error -> bail out
-                               signalled = SIGHUP;
+                               bb_got_signal = SIGHUP;
                                break;
                        }
                }
@@ -175,5 +188,5 @@ done:
        if (device_lock_file)
                unlink(device_lock_file);
 
-       return signalled;
+       return bb_got_signal;
 }