From: git Date: Mon, 16 Feb 2026 13:54:40 +0000 (-0500) Subject: minor tweaks and cleanup, added README X-Git-Url: https://git.datadissipation.net/?a=commitdiff_plain;h=72a27e6d9960362aab5168287cef65ad47438ed6;p=ust.git minor tweaks and cleanup, added README --- diff --git a/README.md b/README.md new file mode 100644 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 9d00fab..68ca64c 100644 --- 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)