]> datadissipation.net git - ust.git/commitdiff
Major overhaul, various fixes for buffer processing functions
authorgit <redacted>
Wed, 18 Feb 2026 12:39:58 +0000 (07:39 -0500)
committergit <redacted>
Wed, 18 Feb 2026 12:39:58 +0000 (07:39 -0500)
Makefile
config.mk [new file with mode: 0644]
ust.c

index be20f2638798a98074bc533fa795b2b88ab493f2..94e4831e6b2baa9cb79c8b7874fd7b4a773c4fb3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,9 @@
-VERSION = 0.1.0
+include config.mk
 
 TARGET = ust
 SRC = ust.c
 OBJ = ${SRC:.c=.o}
 
-PREFIX = /usr/local
-
-OS != uname -s
-
-GNUSRC != if [ "${OS}" = "Linux" ]; then \
-       printf "%s" "-D_GNU_SOURCE"; \
-fi
-
 all: ${TARGET}
 
 ${SRC}: config.h
@@ -22,7 +14,7 @@ config.h:
 clean:
        rm -f *.[oa] ${TARGET}
 
-install:
+install: all
        mkdir -p ${PREFIX}/bin
        cp -f ${TARGET} ${PREFIX}/bin
        chmod 755 ${PREFIX}/bin/${TARGET}
@@ -30,9 +22,4 @@ install:
 uninstall:
        rm -f ${PREFIX}/bin/${TARGET}
 
-CFLAGS = -std=c99 -Wall -pthread -O2 ${GNUSRC}
-LDFLAGS = 
-
-CC = cc
-
 .PHONY: all clean install uninstall 
diff --git a/config.mk b/config.mk
new file mode 100644 (file)
index 0000000..5a4c80e
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,15 @@
+VERSION = 0.2.1
+
+PREFIX = /usl/local
+
+# need -D_GNU_SOURCE wehn compiling on Linux
+OS != uname -s
+
+GNUSRC != if [ "${OS}" = "Linux" ]; then \
+       printf "%s" "-D_GNU_SOURCE"; \
+fi
+
+CFLAGS = -std=c99 -Wall -pthread -O2 ${GNUSRC}
+LDFLAGS = 
+
+CC = cc
diff --git a/ust.c b/ust.c
index 9c2c57f63cc6a318ef76830e2ca8d0458a7b91c1..7d5ac69f8306a830c6a15e8e99cdace5a0fe50d2 100644 (file)
--- a/ust.c
+++ b/ust.c
@@ -1,6 +1,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <limits.h>
 #include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #define IXONXOFF (IXON | IXOFF)
 
 typedef struct {
-       ssize_t sizem;
        char find;
        char input;
-       int offset;
+       int offset; /* can only be a 1 or a -1 */
 } Args; 
 
+typedef struct {
+       ssize_t sizebm;
+       ssize_t sizesm;
+} Sizes;
+
 static int gettermattr(int dv, void *strct);
 static int settermattr(int dv, const void *strct);
 static void settermspd(unsigned int lispeed, unsigned int lospeed, const void *strct);
@@ -43,14 +48,15 @@ static int openport();
 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 inline unsigned int lsbmask(unsigned int n);
 static inline int termchck(const void *term);
 static void interchck();
 static void cechck();
 static void *writeport(void *unused);
 static void *readport(void *unused);
 static void getcmd(int escape);
-static inline void replacechar(char *buff, ssize_t sread, const Args *args);
-static inline ssize_t addchar(char *buff, ssize_t sread, int *scratch, const Args *args);
+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);
 static inline ssize_t rmchar(char *buff, ssize_t sread, int *scratch, const Args *args);
 static void sighandl(int signo);
 static void die(int code, const char *msg, ...);
@@ -61,13 +67,17 @@ static void die(int code, const char *msg, ...);
  static struct termios cntrl, origterm = {0}, newterm = {0};
 #endif
 
+static Args bsargs = {DEL, DEL, 0};
+static Args nocrargs = {CR, 0, 0};
+static Args nolfargs = {LF, '\0', 0}; /* null-terminator to use*/
+static Args lfincrargs = {CR, LF, 1};
+static Args crinlfargs = {LF, CR, -1};
 static const unsigned int uintmax = ~(unsigned int)0; /* unsigned -1 to return on error */
 static struct timespec wts;
 static char *writebuff = NULL;
 static char *readbuff = NULL;
 static int *scratchr = NULL;
 static int *scratchw = NULL;
-static char backspc = DEL,tbackspc = DEL;
 static int fd = -1;
 static int interactive = 0;
 
@@ -190,6 +200,9 @@ openport()
        if (settermattr(fd, &cntrl) == -1)
                die(2, "failed to set flow control\n");
 
+       cntrl.c_iflag &= ~(ICRNL | INLCR);
+       cntrl.c_oflag &= ~(OCRNL | ONLRET | ONLCR);
+
        if (setroptions())
                die(2, "failed to set cr-lf translation options\n");
 
@@ -290,34 +303,24 @@ troptions(CRLFOpt *options, const char *str)
 int
 setroptions()
 {
-       if (itropts.crtolf)
-               cntrl.c_iflag |= ICRNL;
-       else
-               cntrl.c_iflag &= ~ICRNL;
-
-       if (itropts.lftocr)
-               cntrl.c_iflag |= INLCR;
-       else
-               cntrl.c_iflag &= ~INLCR;
-
-       if (tropts.crtolf)
-               cntrl.c_oflag |= OCRNL;
-       else
-               cntrl.c_oflag &= ~OCRNL;
-
-       if (tropts.lftocr)
-               cntrl.c_oflag |= ONLRET;
-       else
-               cntrl.c_oflag &= ~ONLRET;
-
-       if (tropts.crinlf)
-               cntrl.c_oflag |= ONLCR;
-       else    
-               cntrl.c_oflag &= ~ONLCR;
+       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));
 
        return settermattr(fd, &cntrl);
 }
 
+inline unsigned int
+lsbmask(unsigned int n)
+{
+       /* if n == 1, n fills with all 1s, 0 stays the same */ 
+       for (int i = (sizeof(int) * CHAR_BIT); i > 0; i--)
+               n |= (n << 1);
+       return n;
+}
+
 inline int
 termchck(const void *term)
 {
@@ -338,11 +341,15 @@ termchck(const void *term)
 void *
 writeport(void *unused)
 {
+       Sizes msizes;
        struct timespec ts;
        ts.tv_sec = swritedelay;
        ts.tv_nsec = nswritedelay;
        wts.tv_sec = 0;
        wts.tv_nsec = chardelay;
+       msizes.sizesm = scratchwsz;
+       msizes.sizebm = wbuffsz;
+
        writebuff = malloc(wbuffsz * sizeof(char));
        scratchw = malloc(scratchwsz * sizeof(int));
        
@@ -353,17 +360,6 @@ writeport(void *unused)
        
        int escape = 0;
 
-       Args bsargs, nocrargs, nolfargs, lfincrargs;
-       bsargs.sizem = wbuffsz;
-       nocrargs = nolfargs  = lfincrargs = bsargs;
-
-       bsargs.find=backspc; bsargs.input=tbackspc;
-
-       nocrargs.find = CR;
-       nolfargs.find = LF;
-
-       lfincrargs.find = CR; lfincrargs.input = LF; lfincrargs.offset = 1;
-
        for (;;) {
                ssize_t inln = read(STDIN_FILENO, writebuff, wbuffsz - 1);
                if (inln > 0) { 
@@ -378,15 +374,14 @@ writeport(void *unused)
                                        escape = 1; 
                        }
 
-                       if (backspc != tbackspc)
+                       if (bsargs.find != bsargs.input)
                                replacechar(writebuff, inln, &bsargs);
-
                        if (tropts.nocr)
                                inln = rmchar(writebuff, inln, scratchw, &nocrargs);
                        if (tropts.nolf)
                                inln = rmchar(writebuff, inln, scratchw, &nolfargs);
                        if (tropts.lfincr)
-                               inln = addchar(writebuff, inln, scratchw, &lfincrargs);
+                               inln = addchar(writebuff, inln, scratchw, &msizes, &lfincrargs);
                        
                        if (inln > 1) {
                                for (int i = 0; i <= inln; i++) {
@@ -405,9 +400,13 @@ writeport(void *unused)
 void *
 readport(void *unused)
 {
+       Sizes msizes;
        struct timespec ts;
        ts.tv_sec = sreaddelay;
        ts.tv_nsec = nsreaddelay;
+       msizes.sizesm = scratchrsz;
+       msizes.sizebm = rbuffsz;
+
        readbuff = malloc(rbuffsz * sizeof(char));
        scratchr = malloc(scratchrsz * sizeof(int));
        
@@ -418,16 +417,6 @@ readport(void *unused)
        
        interchck();
 
-       Args nocrargs, nolfargs, crinlfargs, lfincrargs;
-       nocrargs.sizem = rbuffsz;
-       nolfargs  = crinlfargs = lfincrargs = nocrargs;
-
-       nocrargs.find = CR;
-       nolfargs.find = LF;
-
-       lfincrargs.find = CR; lfincrargs.input = LF; lfincrargs.offset = 1;
-       crinlfargs.find = LF; crinlfargs.input = CR; crinlfargs.offset = -1;
-
        /* disable stdout buffering */
        setvbuf(stdout, NULL, _IONBF, 0);
 
@@ -439,9 +428,9 @@ readport(void *unused)
                        if (itropts.nolf)
                                outln = rmchar(readbuff, outln, scratchr, &nolfargs);
                        if (itropts.crinlf)
-                               outln = addchar(readbuff, outln, scratchr, &crinlfargs);
+                               outln = addchar(readbuff, outln, scratchr, &msizes, &crinlfargs);
                        if (itropts.lfincr)
-                               outln = addchar(readbuff, outln, scratchr, &lfincrargs);
+                               outln = addchar(readbuff, outln, scratchr, &msizes, &lfincrargs);
 
                        write(STDOUT_FILENO, readbuff, outln);
                }
@@ -460,33 +449,38 @@ replacechar(char *buff, ssize_t size, const Args *args)
                        buff[i] = args->input;
 }
 
-/* TODO: optimize the function and allow for offsets greater than 1 */
 inline ssize_t __attribute__((hot))
-addchar(char *buff, ssize_t size, int *scratch, const Args *args)
+addchar(char *buff, ssize_t size, int *scratch, const Sizes *sizes, const Args *args)
 {
-       int c = 0;
+       int to, c;
+       c = 0;
+       /* turns negative numbers into 1, positive into 0 */
+       to = ((args->offset >> ((sizeof(int) * CHAR_BIT) - 1)) & 1);
 
        for (int i = 0; i < size; i++) {
                if (buff[i] == args->find) {
                        scratch[c] = i;
                        c++;
                }
+               if (c >= sizes->sizesm)
+                       break;
        }
        if (!c)
                return(size);
-       if ((size + c) > args->sizem)
-               c = args->sizem - size;
-       
-       if (scratch[0] == 0 && args->offset < 0) {
-               memmove(&buff[0]+1, &buff[0], size);
-               scratch[0] = 1;
+       if (size == 1 && c == 1 && scratch[0] == 0) {
+               buff[to ^ 1] = args->input;
+               buff[to] = args->find;
+               return 2;
        }
-       for (int i = c; i > 0; i--) {
+       if ((size + c) > sizes->sizebm)
+               c = sizes->sizebm - size;
+
+       for (int i = c - 1; i >= 0; i--) {
                int t = scratch[i];
-               for (int s = size; s >= t;s--)
-                       buff[s + args->offset] = buff[s];
-               buff[t] = args->input;
+               memmove(&buff[t] + 1, &buff[t], (size + c) - t);
+               buff[t + (to ^ 1)] = args->input;
        }
+       printf("%s\n", buff);
        return (size + c);
 }
 
@@ -494,7 +488,6 @@ inline ssize_t __attribute__((hot))
 rmchar(char *buff, ssize_t size, int *scratch, const Args *args)
 {
        int c = 0;
-
        for (int i = 0; i < size; i++) {
                if (buff[i] == args->find) {
                        scratch[c] = i;
@@ -503,11 +496,13 @@ rmchar(char *buff, ssize_t size, int *scratch, const Args *args)
        }
        if (!c)
                return(size);
+       if (size == 1 && c == 1 && scratch[0] == 0)
+               return 0;
 
-       for (int i = c; i > 0; i--)
-               for (int s = size; s >= scratch[i]; s--)
-                       buff[s] = buff[s + 1];
-
+       for (int i = c; i >= 0; i--) {
+               int t = scratch[i];
+               memmove(&buff[t], &buff[t] + 1, (size + c) - t);
+       }
        return(size - c);
 }
 
@@ -535,11 +530,11 @@ interchck()
                newterm.c_cc[VQUIT] = _POSIX_VDISABLE;
 
                if (backspace)
-                       tbackspc = BS;
+                       bsargs.input = BS;
                else
-                       tbackspc = DEL;
+                       bsargs.input = DEL;
 
-               backspc = origterm.c_cc[VERASE];
+               bsargs.find = origterm.c_cc[VERASE];
 
                if (settermattr(STDOUT_FILENO, &newterm) < 0)
                        die(1, "failed to set terminal attributes\n");
@@ -562,14 +557,15 @@ cechck()
 void
 getcmd(int escape)
 {
-       Args rmlf;
+       Sizes msizes;
+       msizes.sizesm = scratchwsz;
+       msizes.sizebm = wbuffsz;
+
        char cmdchar;
        char ttr[64];
        unsigned int tspd;
 
-       rmlf.find = LF; rmlf.input = '\0';
-
-       if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO))
+       if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
                interactive = 1;
 
        interchck();
@@ -585,17 +581,17 @@ getcmd(int escape)
                break;
        case 'b':
                if (backspace)
-                       tbackspc = DEL;
+                       bsargs.input = DEL;
                else
-                       tbackspc = BS;
-               backspace = !backspace;
+                       bsargs.input = BS;
+               backspace ^= 1;
                break;
        case 'h':
                if (half)
                        newterm.c_lflag &= ~ECHO;
                else
                        newterm.c_lflag |= ECHO;
-               half = !half;
+               half ^= 1;
                if (settermattr(STDOUT_FILENO, &newterm) < 0)
                        die(1, "failed to set terminal attributes\n");
                break;
@@ -604,22 +600,29 @@ getcmd(int escape)
                        newterm.c_lflag &= ~ICANON;
                else
                        newterm.c_lflag |= ICANON;
-               canonical = !canonical;
+               canonical ^= 1;
                if (settermattr(STDOUT_FILENO, &newterm) < 0)
                        die(1, "failed to set terminal attributes\n");
                break;
        case 'w':
                cechck();
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &rmlf);
+                       replacechar(ttr, 63, &nolfargs);
                        ssize_t frln;
                        int wfd = open(ttr, O_RDONLY);
-                       if (fd == -1) {
+                       if (wfd == -1) {
                                perror("error opening file");
-                               break;
+                               goto finish;
                        }
                        while ((frln = read(wfd, writebuff, wbuffsz - 1)) > 0) {
                                for (int i = 0; i <= frln; i++) {
+                                       if (tropts.nocr)
+                                               frln = rmchar(writebuff, frln, scratchw, &nocrargs);
+                                       if (tropts.nolf)
+                                               frln = rmchar(writebuff, frln, scratchw, &nolfargs);
+                                       if (tropts.lfincr)
+                                               frln = addchar(writebuff, frln, scratchw, &msizes, &lfincrargs);
+       
                                        write(fd, &writebuff[i], 1);
                                        nanosleep(&wts, NULL);
                                }
@@ -629,7 +632,7 @@ getcmd(int escape)
        case 's':
                cechck();
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &rmlf);
+                       replacechar(ttr, 63, &nolfargs);
                        tspd = strtoui(ttr, "invalid speed\n", 0);
                        if (tspd != uintmax) {
                                ospeed = ispeed = tspd;
@@ -643,7 +646,7 @@ getcmd(int escape)
        case 'd':
                cechck();
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &rmlf);
+                       replacechar(ttr, 63, &nolfargs);
                        chardelay = strtoui(ttr, "invalid delay\n", 0);
                        if (chardelay != uintmax) {
                                wts.tv_sec = 0;
@@ -655,7 +658,7 @@ getcmd(int escape)
                cechck();
                fprintf(stderr, "additional output translation option: ");
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &rmlf);
+                       replacechar(ttr, 63, &nolfargs);
                        if(troptions(&tropts, ttr))
                                goto finish;
                        if (setroptions())
@@ -666,7 +669,7 @@ getcmd(int escape)
                cechck();
                printf("additional input translation option: ");
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &rmlf);
+                       replacechar(ttr, 63, &nolfargs);
                        if (troptions(&itropts, ttr))
                                goto finish;    
                        if (setroptions())
@@ -898,7 +901,7 @@ main(int argc, char **argv)
        if (!rxspdset)
                ispeed = ospeed;
 
-       if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO))
+       if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
                interactive = 1;
 
        signal(SIGHUP, sighandl);