]> datadissipation.net git - ust.git/commitdiff
minor tweaks and cleanup, added README
authorgit <redacted>
Mon, 16 Feb 2026 13:54:40 +0000 (08:54 -0500)
committergit <redacted>
Mon, 16 Feb 2026 13:54:40 +0000 (08:54 -0500)
README.md [new file with mode: 0644]
ust.c

diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..1495043
--- /dev/null
+++ b/README.md
@@ -0,0 +1,50 @@
+##Flags
+
+All flags can have their default values set by modifying `config.h`, additional info and configuration options are also available in the file
+
+ * `--line|-l dev` - device to open, can be specified with `/dev/` or as just the device name
+ * `--verbose|-v` - toggle verbose output
+ * `--speed|-s # | -#` - baudrate, can also be set with just the number
+ * `--rx-speed|-i` - separate baudrate for RX line, same as TX if not set explicitly
+ * `--data|-D bits` - set data bits
+ * `--stop-bits|-S bits` - set stop bits 
+ * `--software|-X` - toggle XON/XOFF flow control
+ * `--delay|-d delay` - delay between sending characters in nanoseconds
+ * `--min-chars|-m` - the minimum number of characters to start sending them
+ * `--backspace|-b` - toggle between ASCII `DELETE` and `BACKSPACE` characters
+ * `--echo|-h` - toggle local echo (half-duplex mode)
+ * `--canonical|-c` - toggle canonical mode (text can be edited locally before sending it to the line)
+> If both even and odd parity flags are set, parity is disabled
+ * `--odd|-o` - toggle odd parity
+ * `--even|-e` - toggle even parity
+> If both hardware flow control flags are set, DCD flow control is enabled
+ * `--hardware-rts-cts|-R` - toggle RTS/CTS flow control
+ * `--hardware-dtr-dsr|-r` - toggle DTR/DSR flow control
+
+---
+
+ * `--translation|-t option` - CR and LF translation for data sent
+ * `--input-translation|-T option` - CR and LF translation for data read
+###Options:
+ * `cr-to-lf`
+ * `cr-in-lf` - CR to CRLF
+ * `no-cr`
+ * `lf-to-cr`
+ * `lf-in-cr` - LF to CRLF
+ * `no-lf`
+
+##Interactive use
+
+Special character (`~` by default, may be set in `config.h`) will be escaped if it's the first one in the buffer.
+
+###Commands
+
+ * `.` - drop connection and exit
+ * `b` - toggle backspace character
+ * `h` - toggle local echo
+ * `c` - toggle canonical mode
+ * `s` - set new baudrate
+ * `d` - set new character delay
+ * `t|T` - toggle a translation option for output|input
+ * `w` - write file contents to the line
+ * `p` - send a DCD pulse
diff --git a/ust.c b/ust.c
index 9d00fab98229c71d1eb0343c38b74a2294ecf539..68ca64c9142179a1780d9189d6e714f3ff6f6773 100644 (file)
--- a/ust.c
+++ b/ust.c
@@ -81,7 +81,7 @@ main(int argc, char **argv)
        }
 
        static struct option longopt[] = {
-               {"device", required_argument, NULL, 'l'},
+               {"line", required_argument, NULL, 'l'},
                {"speed", required_argument, NULL, 's'},
                {"rx-speed", required_argument, NULL, 'i'},
                {"echo", no_argument, NULL, 'h'},
@@ -109,20 +109,24 @@ main(int argc, char **argv)
                        case 0: 
                                break;
                        case 'b':
-                               backspace = !backspace; break;
+                               backspace ^= 1; break;
                        case 'c':
-                               canonical = !canonical; break;
+                               canonical ^= 1; break;
                        case 'R':
                                hard ^= 1; break;
                        case 'r':
                                hard ^= 2; break;
                        case 'X':
-                               soft = !soft; break;
-                       case 'd':
-                               tui = strtoui(optarg, "invalid delay: %s\n", 0);
-                               if (tui == uintmax)
+                               soft ^= 1; break;
+                       case 'd':;
+                               char* endptr;
+                               long t = strtol(optarg, &endptr, 10);
+                               if (errno != 0 || *endptr != '\0' || t < 0) {
+                                       fprintf(stderr, "invalid character delay\n");
                                        goto ustusage;
-                               chardelay = tui;
+                               } else {
+                                       chardelay = t;
+                               }
                                break;
                        case 'D':
                                if (strlen(optarg) != 1 || !(optarg[0] >= '5' && optarg[0] <= '8')) {
@@ -137,13 +141,13 @@ main(int argc, char **argv)
                        case 'o':
                                parity ^= 2; break;
                        case 'h':
-                               half = !half; break;
+                               half ^= 1; break;
                        case 'i':
                                tui = strtoui(optarg, "invalid rx speed: %s\n", 1);
                                if (tui == uintmax)
                                        goto ustusage;
                                ispeed = tui;
-                               rxspdset = !rxspdset;
+                               rxspdset = 1;
                                break;
                        case 's':
                                tui = strtoui(optarg, "invalid speed: %s\n", 1);
@@ -152,7 +156,7 @@ main(int argc, char **argv)
                                ospeed = tui;
                                break;
                        case 'S':
-                               stopb = !stopb; break;
+                               stopb ^= 1; break;
                        case 'l':
                                if (devset) {
                                        fprintf(stderr, "cannot specify multiple devices\n");
@@ -163,11 +167,9 @@ main(int argc, char **argv)
                                        goto ustusage;
                                }
                                if (strchr(optarg, '/')) {
-                                       line[0] = '\0';
                                        strcpy(line, optarg);
                                        devset = 1;
                                } else {
-                                       line[0] = '\0';
                                        sprintf(line, "/dev/%s", optarg);
                                        devset = 1;
                                }
@@ -187,10 +189,10 @@ main(int argc, char **argv)
                                        goto ustusage;
                                break;
                        case 'v':
-                               verbose = !verbose; break;
+                               verbose ^= 1; break;
                        default:
                        ustusage:
-                               die(2, "usage: ust [--device|-l dev] [--speed|-s #|-#] [--rx-speed|-i #]\n"
+                               die(2, "usage: %s [--line|-l line] [--speed|-s #|-#] [--rx-speed|-i #]\n"
                                                "           [--data-bits|-D #] [--stop-bits|-S]"
                                                " [--even|-e] [--odd|-o]\n"
                                                "           [--hardware-rtscts|-R]"
@@ -199,12 +201,14 @@ main(int argc, char **argv)
                                                " [--canonical|-c] [--echo|-h]\n"
                                                "           [--translation|-t tropt]"
                                                " [--input-translation|-T tropt]\n"
-                                               "           [--verbose|-v] [--backspace|-b]\n");
+                                               "           [--verbose|-v] [--backspace|-b]\n",
+                                               argv[0]);
                                break;
                }
        
        
        }
+
        if (!rxspdset)
                ispeed = ospeed;
 
@@ -221,12 +225,6 @@ main(int argc, char **argv)
        pthread_t readthread, writethread;
        pthread_create(&writethread, NULL, writeport, NULL);
        pthread_create(&readthread, NULL, readport, NULL);
-       
-       pthread_join(writethread, NULL);
-       pthread_join(readthread, NULL);
-       close(fd);
-       return 0;
-
 }
 
 int
@@ -263,7 +261,6 @@ settermspd(unsigned int lispeed, unsigned int lospeed, void *strct)
         optst->c_cflag |= BOTHER;
         optst->c_ispeed = ispeed;
         optst->c_ospeed = ospeed;
-
        #else
         struct termios *optst = (struct termios*)strct;
         cfsetispeed(optst, ispeed);
@@ -274,37 +271,35 @@ settermspd(unsigned int lispeed, unsigned int lospeed, void *strct)
 int
 openport()
 {
+       if (verbose) fprintf(stderr, "opening \"%s\"\n", line);
+
        fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY);
        if (fd == -1) {
                perror("error opening device");
                exit(1);
        }
 
-       if (verbose) fprintf(stderr, "opened \"%s\"\n", line);
+       if (verbose) fprintf(stderr, "checking if \"%s\" is a TTY\n", line);
 
        if (!isatty(fd))
                die(2, "device \"%s\" is not a TTY\n", line);
-       
-       if (verbose) fprintf(stderr, "\"%s\" is a TTY\n", line);
 
        int flags = fcntl(fd, F_GETFL, 0);
        flags &= ~(O_NONBLOCK | O_NDELAY); /* opened to check with non-blocking mode, now set to blocking */
-
-       if (fcntl(fd, F_SETFL, flags) != 0)
+       if (fcntl(fd, F_SETFL, flags) == -1)
                die(1, "failed to set the device to blocking mode\n");
                
-       if (gettermattr(fd, &cntrl) != 0)
+       if (gettermattr(fd, &cntrl) == -1)
                 die(1, "failed to get device attributes\n");
        
        if (verbose) fprintf(stderr, "setting baudrate [RX:%u | TX:%u]\n", ispeed, ospeed);
        
        settermspd(ispeed, ospeed, &cntrl);
-       if (settermattr(fd, &cntrl) != 0)
+       if (settermattr(fd, &cntrl) == -1)
                 die(2,"failed to set baudrate [RX:%u | TX:%u]\n",  ispeed, ospeed);
 
        cntrl.c_lflag = 0;
        cntrl.c_iflag &= ~(ISTRIP | BRKINT);
-
        cntrl.c_cflag &= ~(PARENB | PARODD);
 
        if (verbose) fprintf(stderr, "setting parity [even: %d, odd: %d]\n", parity & 1, (parity & 2) >> 1);
@@ -314,7 +309,7 @@ openport()
        if (parity == 2)
                cntrl.c_cflag |= PARENB | PARODD;
        
-       if (settermattr(fd, &cntrl) != 0)
+       if (settermattr(fd, &cntrl) == -1)
                die(2, "failed to set parity [even: %d, odd: %d]\n", parity & 1, (parity & 2) >> 1);
        
        if (verbose) {
@@ -334,7 +329,8 @@ openport()
                cntrl.c_cflag |= CRTSCTS;
        } else if (hard == 2) {
                #ifndef CDTRDSR
-                fprintf(stderr, "DTR/DSR flow control is not supported on this platform\nenabling this option does nothing!\n");
+                fprintf(stderr, "DTR/DSR flow control is not supported on this platform\n"
+                                "enabling this option does nothing!\n");
                #else
                 cntrl.c_lflag |= CDTRDSR;
                #endif
@@ -345,7 +341,7 @@ openport()
                #endif
        }
 
-       if (settermattr(fd, &cntrl) != 0)
+       if (settermattr(fd, &cntrl) == -1)
                die(2, "failed to set flow control\n");
 
        if (setroptions())
@@ -367,7 +363,7 @@ openport()
        cntrl.c_cflag &= ~CSIZE;
        cntrl.c_cflag |= db;
 
-       if (settermattr(fd, &cntrl) != 0)
+       if (settermattr(fd, &cntrl) == -1)
                die(2, "failed to set data bits [%c]\n", datab);
        
        if (verbose) fprintf(stderr, "setting stop bits [%d]\n", stopb+1);
@@ -377,8 +373,8 @@ openport()
        else
                cntrl.c_cflag &= ~CSTOPB;
 
-       if (settermattr(fd, &cntrl) != 0)
-                die(1, "failed to set stop bits\n");
+       if (settermattr(fd, &cntrl) == -1)
+                die(1, "failed to set stop bits [%d]\n", stopb+1);
 
        #ifdef __linux__
         ioctl(fd, TCFLSH, TCIOFLUSH);
@@ -544,9 +540,6 @@ writeport(void *unused)
                }
                nanosleep(&ts, NULL);
        }
-
-       free(writebuff); free(scratchw);
-       writebuff = NULL; scratchw = NULL;
        return NULL;
 }
 
@@ -566,6 +559,7 @@ readport(void *unused)
        
        interchck();
 
+       /* disable stdout buffering */
        setvbuf(stdout, NULL, _IONBF, 0);
 
        for (;;) {
@@ -586,9 +580,6 @@ readport(void *unused)
        }
        if (isatty(STDIN_FILENO)) 
                settermattr(STDIN_FILENO, &origterm);
-
-       free(readbuff); free(scratchr);
-       readbuff = NULL; scratchr = NULL;
        return NULL;
 }
 
@@ -616,7 +607,7 @@ addchar(char *str, int *scratch, ssize_t size, const size_t bsize,const char fin
        if ((size + c) > bsize)
                c = bsize - size;
        
-       if (scratch[0] == 0) {
+       if (scratch[0] == 0 && offset < 0) {
                memmove(&str[0]+1, &str[0], size);
                scratch[0] = 1;
        }
@@ -714,7 +705,7 @@ getcmd(int escape)
 
        switch (cmdchar) {
                case '.':
-                       die(0,"\r\n[EOT]\r\n");
+                       die(0,"\n[EOT]\n");
                        break;
                case 'b':
                        if (backspace)