From: git Date: Wed, 18 Feb 2026 12:39:58 +0000 (-0500) Subject: Major overhaul, various fixes for buffer processing functions X-Git-Url: https://git.datadissipation.net/?a=commitdiff_plain;h=79a37dfd33d18d53982d9c72fac2b089abaaccaa;p=ust.git Major overhaul, various fixes for buffer processing functions --- diff --git a/Makefile b/Makefile index be20f26..94e4831 100644 --- 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 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 9c2c57f..7d5ac69 100644 --- a/ust.c +++ b/ust.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -30,12 +31,16 @@ #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);