]> datadissipation.net git - ust.git/commitdiff
refine redirected i/o timeout mechanism, remove obsoleted flags
authorgit <redacted>
Mon, 2 Mar 2026 07:43:10 +0000 (02:43 -0500)
committergit <redacted>
Mon, 2 Mar 2026 07:43:10 +0000 (02:43 -0500)
minor formatting changes and version bump

README.md
config.def.h
config.mk
ust.1
ust.c

index d60c01188df60be0ad555abc92adb58a054ee990..44d3f5058d8f62fea6e1940372275700849776c8 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
 ## Installation
 
-Before installing check config.mk - inside, the installation directories can be set.
+Before installing check `config.mk` - inside, the installation directories can be set.
 
 To install, simply run:
 
 ```
-make install
+make && make install
 ```
index e9df03809fe0c5a49ab4ed6ce3a4ba8fce72363d..44583ca83ac567e486fa529e39eb039124220e94 100644 (file)
@@ -10,7 +10,7 @@ const size_t scratchrsz = 256;
 const long swritedelay = 0; /* seconds */
 const long nswritedelay = 1000000; /* nanoseconds */
 
-/* other names follow the same logic as above */
+/* other time variable names follow the same logic as above */
 
 const long sreaddelay = 0;
 const long nsreaddelay = 1000000;
@@ -36,10 +36,6 @@ const char escapechar = '~';
 /* print additional info to stderr */
 int verbose = 0; /*(0|1)*/
 
-/* exit timeout after piped ust reaches EOF */
-long stimeout = 0;
-long nstimeout = 10000;
-
 /*
  * device name
  *
index 36893ea88a9f8613c2cccfcb7a41b4ef75a3f08c..31f86192e3fe7e4689fe074f3da5c1d3667aa6d5 100644 (file)
--- a/config.mk
+++ b/config.mk
@@ -1,4 +1,4 @@
-VERSION = 0.2.1
+VERSION = 0.2.3
 
 TARGET = ust
 
@@ -11,8 +11,11 @@ OS != uname -s
 GNUSRC != if [ "${OS}" = "Linux" ]; then \
        printf "%s" "-D_GNU_SOURCE"; \
 fi
+# some implementations of make do not accept `!=`,
+# so if it triggers any errors just remove this block
+# and add the flag manually
 
-CFLAGS = -std=c99 -Wall -pthread -O2 ${GNUSRC}
+CFLAGS = -std=c99 -Wall -lpthread -O2 ${GNUSRC}
 LDFLAGS = 
 
 CC = cc
diff --git a/ust.1 b/ust.1
index dd7c132ed80b2061d3c040bba4eed148c290e798..5e481499ee836568b5b099b5869f15378c7a3410 100644 (file)
--- a/ust.1
+++ b/ust.1
@@ -17,8 +17,6 @@
 .Op Fl \-hardware\-dtr\-dsr|\-R
 .Op Fl \-software|\-X
 .Op Fl \-delay|\-d Ar #
-.Op Fl \-timeout\-ns|\-f Ar #
-.Op Fl \-timeout\-s|\-F Ar #
 .Op Fl \-min\-chars|\-m Ar #
 .Op Fl \-canonical|\-c
 .Op Fl \-echo|\-h
@@ -76,17 +74,6 @@ Toggle DTR/DSR flow control (setting both hardware flow control options will ena
 Toggle XON/XOFF software flow control (can be enabled with hardware flow control simultaneously).
 .It Fl \-delay|\-d Ar #
 Delay between sending multiple characters (when redirecting stdin or writing a file) to the line in nanoseconds.
-.It Fl \-timeout\-ns|\-f Ar #
-With stdin redirected,
-.Nm
-will exit upon reaching 
-.Ar EOF ,
-this option sets a delay (in nanoseconds) after
-.Ar EOF
-encounter and before program exit.
-.It Fl \-timeout\-s|\-F Ar #
-.Ar EOF
-exit delay (in seconds).
 .It Fl \-min\-chars|\-m Ar #
 The minimum of characters to input before they get sent to the line.
 .It Fl \-canonical|\-c
diff --git a/ust.c b/ust.c
index e88bdccc104a2479dd8571bfeb9c0ab885a4d9c5..7d4918c96268e1b48dd17ed7bd5cc8e707174e56 100644 (file)
--- a/ust.c
+++ b/ust.c
@@ -2,7 +2,6 @@
 #include <sys/ioctl.h>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <limits.h>
 #include <signal.h>
 #include <stdarg.h>
@@ -11,6 +10,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <fcntl.h>
 #include <getopt.h>
 #include <pthread.h>
 
@@ -66,16 +66,16 @@ typedef struct {
 static int gettermattr(int dv, struct TERMIOS_STRUCT *optst);
 static int settermattr(int dv, const struct TERMIOS_STRUCT *optst);
 static void settermspd(unsigned int lispeed, unsigned int lospeed, struct TERMIOS_STRUCT *optst);
-static int openport();
+static int openport(void);
 static unsigned int strtoui(const char *str, const char *msg, unsigned int min);
 static int troptions(CRLFOpt *options, const char *str);
-static int setroptions();
+static int setroptions(void);
 static inline unsigned int lsbmask(unsigned int n);
 static inline int termchck(const struct TERMIOS_STRUCT *term);
-static void interchck();
-static void cechck();
-static void *writeport(void *unused);
-static void *readport(void *unused);
+static void interchck(void);
+static void cechck(void);
+static void *writeport(void *);
+static void *readport(void *);
 static void getcmd(int escape);
 static inline void replacechar(char *buff, ssize_t size, const Args *args);
 static inline ssize_t addchar(char *buff, ssize_t size, int *scratch, const Sizes *msizes, const Args *args);
@@ -101,6 +101,7 @@ static char *readbuff = NULL;
 static int *scratchr = NULL;
 static int *scratchw = NULL;
 static int fd = -1;
+static long rwc = 0;
 
 int
 gettermattr(int dv, struct TERMIOS_STRUCT *optst)
@@ -137,7 +138,7 @@ settermspd(unsigned int lispeed, unsigned int lospeed, struct TERMIOS_STRUCT *op
 }
 
 int
-openport()
+openport(void)
 {
        int flags;
        struct flock fl = { 0 };
@@ -169,12 +170,9 @@ openport()
        if (gettermattr(fd, &cntrl) == -1)
                 die(1, "failed to get device attributes\n");
 
-       fl.l_type = F_WRLCK;
-       fl.l_whence = SEEK_SET;
-       fl.l_start = 0;
-       fl.l_len = 0;
-
        if (exclusive) {
+               fl.l_type = F_WRLCK;
+               fl.l_whence = SEEK_SET;
                if (fcntl(fd, F_SETLK, &fl) == -1) {
                        perror("fcntl");
                        die(1, "failed to lock the device, exiting now\n");
@@ -302,7 +300,7 @@ openport()
 
 unsigned int
 strtoui(const char *str, const char *msg, unsigned int min)
-{
+{      
        long t;
        char *endptr;
 
@@ -357,13 +355,13 @@ troptions(CRLFOpt *options, const char *str)
 }
 
 int
-setroptions()
+setroptions(void)
 {
-       cntrl.c_iflag ^= (ICRNL & lsbmask(itropts.crtolf));
-       cntrl.c_iflag ^= (INLCR & lsbmask(itropts.lftocr));
-       cntrl.c_oflag ^= (OCRNL & lsbmask(tropts.crtolf));
+       cntrl.c_iflag ^= (ICRNL  & lsbmask(itropts.crtolf));
+       cntrl.c_iflag ^= (INLCR  & lsbmask(itropts.lftocr));
+       cntrl.c_oflag ^= (OCRNL  & lsbmask(tropts.crtolf));
        cntrl.c_oflag ^= (ONLRET & lsbmask(tropts.lftocr));
-       cntrl.c_oflag ^= (ONLCR & lsbmask(tropts.crinlf));
+       cntrl.c_oflag ^= (ONLCR  & lsbmask(tropts.crinlf));
 
        return settermattr(fd, &cntrl);
 }
@@ -388,13 +386,11 @@ termchck(const struct TERMIOS_STRUCT *term)
 }
 
 void *
-writeport(void *unused)
+writeport(void *)
 {
        Sizes msizes;
-       struct timespec timeout, ts;
+       struct timespec ts;
 
-       timeout.tv_sec = stimeout;
-       timeout.tv_nsec = nstimeout;
        ts.tv_sec = swritedelay;
        ts.tv_nsec = nswritedelay;
        wts.tv_sec = 0;
@@ -437,19 +433,18 @@ writeport(void *unused)
                        
                        if (inln > 1) {
                                for (int i = 0; i <= inln; i++) {
-                                       write(fd, &writebuff[i], 1);
+                                       rwc -= write(fd, &writebuff[i], 1);
                                        nanosleep(&wts, NULL);
                                }
                        } else {
-                               write(fd, writebuff, 1);
+                               rwc -= write(fd, writebuff, 1);
                        }
                } else if (inln == 0 && !interactive) {
                        break;
                }
                nanosleep(&ts, NULL);
        }
-       /* ust kills itself upon receiving a signal so no fancy `nanosleep()` features needed */
-       nanosleep(&timeout, NULL);
+
        die(0, "[EOF]\n");
 
        /* unreachable */
@@ -491,7 +486,7 @@ readport(void *unused)
                        if (itropts.lfincr)
                                outln = addchar(readbuff, outln, scratchr, &msizes, &lfincrargs);
 
-                       write(STDOUT_FILENO, readbuff, outln);
+                       rwc += write(STDOUT_FILENO, readbuff, outln);
                }
                nanosleep(&ts, NULL);
        }
@@ -500,7 +495,7 @@ readport(void *unused)
        return NULL;
 }
 
-inline void __attribute__((hot))
+inline void
 replacechar(char *buff, ssize_t size, const Args *args)
 {
        for (int i = 0; i < size; i++)
@@ -508,7 +503,7 @@ replacechar(char *buff, ssize_t size, const Args *args)
                        buff[i] = args->input;
 }
 
-inline ssize_t __attribute__((hot))
+inline ssize_t
 addchar(char *buff, ssize_t size, int *scratch, const Sizes *sizes, const Args *args)
 {
        int to, c;
@@ -543,7 +538,7 @@ addchar(char *buff, ssize_t size, int *scratch, const Sizes *sizes, const Args *
        return (size + c);
 }
 
-inline ssize_t __attribute__((hot))
+inline ssize_t
 rmchar(char *buff, ssize_t size, int *scratch, const Args *args)
 {
        int c = 0;
@@ -671,14 +666,15 @@ getcmd(int escape)
        case 'w':
                cechck();
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &nolfargs);
                        ssize_t frln;
                        int wfd = open(ttr, O_RDONLY);
+                       replacechar(ttr, 63, &nolfargs);
                        if (wfd == -1) {
                                perror("error opening file");
                                goto finish;
                        }
                        while ((frln = read(wfd, writebuff, wbuffsz - 1)) > 0) {
+                               rwc += frln;
                                for (int i = 0; i <= frln; i++) {
                                        if (tropts.nocr)
                                                frln = rmchar(writebuff, frln, scratchw, &nocrargs);
@@ -687,7 +683,7 @@ getcmd(int escape)
                                        if (tropts.lfincr)
                                                frln = addchar(writebuff, frln, scratchw, &msizes, &lfincrargs);
        
-                                       write(fd, &writebuff[i], 1);
+                                       rwc -= write(fd, &writebuff[i], 1);
                                        nanosleep(&wts, NULL);
                                }
                        }
@@ -789,6 +785,11 @@ void
 die(int code, const char *msg, ...)
 {
        va_list fpa;
+       while (rwc > 0) {
+               int t = rwc;
+               nanosleep(&wts, NULL);
+               if (t == rwc) break;
+       }
        if (fd != -1)
                close(fd);
 
@@ -812,14 +813,18 @@ die(int code, const char *msg, ...)
 }
 
 int
-main(int argc, char **argv)
+main(int argc, char *argv[])
 {
-       char *t = NULL;
-       /* glibc's `asprintf()` won't set the string to NULL on failure automatically */
+       long tl;
+       char *t;
+       char *endptr;
+       unsigned int tui;
+       int oind, rxspdset, devset, c;
+       oind = rxspdset = devset = 0;
+
        for (int i = 1; i < argc; i++ ) {
                if (argv[i][0] == '-' && argv[i][1] >= '0' && argv[i][1] <= '9') {
-                       asprintf(&t, "-s%s", argv[i] + 1);
-                       if (!t) {
+                       if (asprintf(&t, "-s%s", argv[i] + 1) == -1) {
                                fprintf(stderr, "%s: cannot convert -# to -s#\n", argv[0]);
                                break;
                        }
@@ -841,8 +846,6 @@ main(int argc, char **argv)
                {"data", required_argument, NULL, 'D'},
                {"delay", required_argument, NULL, 'd'},
                {"min-chars", required_argument, NULL, 'm'},
-               {"timeout-ns", required_argument, NULL, 'f'},
-               {"timeout-s", required_argument, NULL, 'F'},
                {"stop-bits", no_argument, NULL, 'S'},
                {"backspace", no_argument, NULL, 'b'},
                {"translation", required_argument, NULL, 't'},
@@ -851,10 +854,7 @@ main(int argc, char **argv)
                {NULL, 0, NULL, 0}
        };
         
-       unsigned int tui;
-       int oind, rxspdset, devset, c;
-       oind = rxspdset = devset = 0;
-       while ((c = getopt_long(argc, argv, "D:F:T:d:f:i:l:m:s:t:RXbcehorv", longopt, &oind)) != -1) {
+       while ((c = getopt_long(argc, argv, "D:T:d:i:l:m:s:t:RXbcehorv", longopt, &oind)) != -1) {
                switch (c) {
                case 0: 
                        break;
@@ -868,25 +868,17 @@ main(int argc, char **argv)
                        hard ^= 2; break;
                case 'X':
                        soft ^= 1; break;
-               case 'd': /* FALLTHROUGH */
-               case 'f':
-               case 'F':;
-                       char* endptr;
-                       long t;
-                       t = strtol(optarg, &endptr, 10);
+               case 'd':
+                       tl = strtol(optarg, &endptr, 10);
                        if (errno != 0 || *endptr != '\0' || t < 0) {
                                fprintf(stderr, "%s: invalid character delay: %s\n", argv[0], optarg);
                                goto ustusage;
-                       } else if (c == 'd') {
-                               chardelay = t;
-                       } else if (c == 'f'){
-                               nstimeout = t;
                        } else {
-                               stimeout = t;
+                               chardelay = tl;
                        }
                        break;
                case 'D':
-                       if (strlen(optarg) != 1 || !(optarg[0] >= '5' && optarg[0] <= '8')) {
+                       if (optarg[1] != '\0' || !(optarg[0] >= '5' && optarg[0] <= '8')) {
                                fprintf(stderr, "%s: invalid number of data bits: %s\n", argv[0], optarg);
                                goto ustusage;  
                        } else {
@@ -899,18 +891,17 @@ main(int argc, char **argv)
                        parity ^= 2; break;
                case 'h':
                        half ^= 1; break;
-               case 'i':
-                       tui = strtoui(optarg, "invalid rx speed: %s\n", 1);
-                       if (tui == uintmax)
-                               goto ustusage;
-                       ispeed = tui;
-                       rxspdset = 1;
-                       break;
+               case 'i': /* FALLTHROUGH */
                case 's':
                        tui = strtoui(optarg, "invalid speed: %s\n", 1);
                        if (tui == uintmax)
                                goto ustusage;
-                       ospeed = tui;
+                       if (c == 'i') {
+                               ispeed = tui; rxspdset = 1;
+                       } else {
+                               ospeed = tui;
+                               ispeed = rxspdset ? ispeed : ospeed;
+                       }
                        break;
                case 'S':
                        stopb ^= 1; break;