]> datadissipation.net git - ust.git/commitdiff
improve OpenBSD pledge call master
authorgit <redacted>
Thu, 16 Apr 2026 06:34:49 +0000 (02:34 -0400)
committergit <redacted>
Thu, 16 Apr 2026 06:34:49 +0000 (02:34 -0400)
ust.c

diff --git a/ust.c b/ust.c
index a9e463336b4ff7e53d84f468542950680a539aa9..4f00a4c21593b7fbac4267f18bb8ebfa926b216b 100644 (file)
--- a/ust.c
+++ b/ust.c
@@ -35,9 +35,9 @@
 #endif
 
 #ifdef __linux__
- typedef struct termios2 term_struct;
+ typedef struct termios2 TermStruct;
 #else
- typedef struct termios  term_struct;
+ typedef struct termios  TermStruct;
 #endif
 
 typedef struct {
@@ -63,19 +63,19 @@ typedef struct {
 /* including here to access CRLFOpt */
 #include "config.h"
 
-static int gettermattr(int dv, term_struct *optst);
-static int settermattr(int dv, const term_struct *optst);
+static int gettermattr(int dv, TermStruct *optst);
+static int settermattr(int dv, const TermStruct *optst);
 static void settermspd(unsigned int lispeed, unsigned int lospeed,
-                       term_struct *optst);
+                       TermStruct *optst);
 static int openport(void);
 static int openparent(void);
 static unsigned int strtoui(const char *str, unsigned int min);
 static int chcktropts(CRLFOpt *options, const char *str);
 static int settropts(void);
 static inline unsigned int lsbmask(unsigned int n);
-static inline int termvalid(const term_struct *term);
+static inline int termvalid(const TermStruct *term);
 static void eninter(void);
-static void enechocan(void);
+static void enusrecho(void);
 static void *writeport(void *);
 static void *readport(void *);
 static void getcmd(int escape);
@@ -87,21 +87,21 @@ static inline ssize_t rmchar(char *buff, ssize_t sread, int *scratch,
 static void sighandl(int signo);
 static void die(int code, const char *msg, ...);
 
-static term_struct cntrl, /* device struct */
+static TermStruct cntrl, /* device struct */
                    /* controlling terminal structs */
-                   origterm = { 0 }, 
+                   origterm = { 0 },
                    newterm  = { 0 };
 
 static Args bsargs = {0, DEL, DEL};
 static const Args nocrargs = {0, CR, 0},
                   /* null-terminator is for use inside `getcmd()` */
-                  nolfargs = {0, LF, '\0'}, 
+                  nolfargs = {0, LF, '\0'},
                   lfincrargs = {1, CR, LF},
                   crinlfargs = {0, LF, CR};
 
 static struct timespec wts;
 /* unsigned -1 used to return an error */
-static const unsigned int uintmax = ~(unsigned int)0; 
+static const unsigned int uintmax = ~(unsigned int)0;
 static int interactive = 0;
 static char *writebuff = NULL;
 static char *readbuff = NULL;
@@ -112,7 +112,7 @@ static int pfd = -1;
 static long rwc = 0;
 
 int
-gettermattr(int dv, term_struct *optst)
+gettermattr(int dv, TermStruct *optst)
 {
         #ifdef __linux__
          return ioctl(dv, TCGETS2, optst);
@@ -122,7 +122,7 @@ gettermattr(int dv, term_struct *optst)
 }
 
 int
-settermattr(int dv, const term_struct *optst)
+settermattr(int dv, const TermStruct *optst)
 {
        #ifdef __linux__
         return ioctl(dv, TCSETS2, optst);
@@ -132,7 +132,7 @@ settermattr(int dv, const term_struct *optst)
 }
 
 void
-settermspd(unsigned int lispeed, unsigned int lospeed, term_struct *optst)
+settermspd(unsigned int lispeed, unsigned int lospeed, TermStruct *optst)
 {
        #ifdef __linux__
         optst->c_cflag &= ~CBAUD;
@@ -140,8 +140,8 @@ settermspd(unsigned int lispeed, unsigned int lospeed, term_struct *optst)
         optst->c_ispeed = lispeed;
         optst->c_ospeed = lospeed;
        #else
-        cfsetispeed(optst, lispeed);
-        cfsetospeed(optst, lospeed);
+        (void)cfsetispeed(optst, lispeed);
+        (void)cfsetospeed(optst, lospeed);
        #endif
 }
 
@@ -150,18 +150,11 @@ openport(void)
 {
        int flags;
        struct flock fl = { 0 };
-
-       #ifdef __OpenBSD__
-        if (pledge("stdio rpath wpath tty flock", NULL) < 0) {
-                 perror("pledge");
-                 die(1, "pledge failed, exiting now\n");
-        }
-       #endif
-
+       
        if (verbose) fprintf(stderr, "opening \"%s\"\n", line);
 
-       fd = open(line, (O_RDWR | O_NOCTTY | O_NDELAY));
-       if (fd == -1) {
+       fd = open(line, (O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY));
+       if (fd < 0) {
                perror("error opening device");
                exit(1);
        }
@@ -176,8 +169,8 @@ openport(void)
                flags &= ~(O_NONBLOCK | O_NDELAY); 
 
                if (fcntl(fd, F_SETFL, flags) < 0) {
-                       perror("fcntl");
-                       die(1, "exiting now\n");
+                   perror("fcntl");
+                   die(1, "exiting now\n");
                }
        }
 
@@ -188,19 +181,21 @@ openport(void)
                fl.l_type = F_WRLCK;
                fl.l_whence = SEEK_SET;
                if (fcntl(fd, F_SETLK, &fl) < 0) {
-                       perror("fcntl");
-                       die(1, "failed to lock the device, exiting now\n");
+                   perror("fcntl");
+                   die(1, "failed to lock the device, exiting now\n");
                }
        }
 
        /*
         * Baud
         */
-       if (verbose) fprintf(stderr, "setting baudrate [RX:%u | TX:%u]\n", ispeed, ospeed);
+       if (verbose) fprintf(stderr, "setting baudrate [RX:%u | TX:%u]\n",
+                            ispeed, ospeed);
 
        settermspd(ispeed, ospeed, &cntrl);
        if (settermattr(fd, &cntrl) < 0)
-                die(2,"failed to set baudrate [RX:%u | TX:%u]\n",  ispeed, ospeed);
+                die(2,"failed to set baudrate [RX:%u | TX:%u]\n",
+                    ispeed, ospeed);
        
        /*
         * Parity
@@ -209,8 +204,8 @@ openport(void)
        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);
+       if (verbose) fprintf(stderr, "setting parity [even: %d, odd: %d]\n",
+                            parity & 1, (parity & 2) >> 1);
 
        if (parity == 1)
                cntrl.c_cflag |= PARENB;
@@ -218,8 +213,8 @@ openport(void)
                cntrl.c_cflag |= PARENB | PARODD;
 
        if (settermattr(fd, &cntrl) < 0)
-               die(2, "failed to set parity [even: %d, odd: %d]\n",\
-                               parity & 1, (parity & 2) >> 1);
+               die(2, "failed to set parity [even: %d, odd: %d]\n",
+                   parity & 1, (parity & 2) >> 1);
 
        /*
         * Flow control
@@ -227,8 +222,10 @@ openport(void)
        if (verbose) {
                /* it's so ugly and beautiful at the same time */
                int t = (((hard & 1) << 1) & (hard & 2)) >> 1;
-               fprintf(stderr, "setting flow control [XON/XOFF: %d, RTS/CTS: %d, DTR/DSR: %d, DCD: %d]\n",\
-                       soft, t ^ ((hard & 1) << 1) >> 1, t ^ (hard & 2) >> 1, t);
+               fprintf(stderr, "setting flow control "
+                       "[XON/XOFF: %d, RTS/CTS: %d, DTR/DSR: %d, DCD: %d]\n",
+                       soft, t ^ ((hard & 1) << 1) >> 1,
+                       t ^ (hard & 2) >> 1, t);
        }
 
        cntrl.c_cflag |= CLOCAL;
@@ -241,8 +238,9 @@ openport(void)
                cntrl.c_cflag |= CRTSCTS;
        } else if (hard == 2) {
                #ifndef CDTRDSR
-                fprintf(stderr, "DTR/DSR flow control is not supported on this platform\n"
-                                "enabling 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
@@ -319,7 +317,7 @@ openparent(void)
        if (verbose) fprintf(stderr, "opening parent terminal\n");
 
        pfd = open("/dev/tty", O_RDWR);
-       if (pfd == -1) {
+       if (pfd < 0) {
                perror("error opening parent terminal fd");
                die(1, "exiting now\n");
        }
@@ -353,27 +351,27 @@ chcktropts(CRLFOpt *options, const char *str)
        switch (str[0]) {
        case 'l':
                if (!strcmp(str, "lf-in-cr")) {
-                       options->lfincr ^= 1; return 0;
+                   options->lfincr ^= 1; return 0;
                } else if (!strcmp(str, "lf-to-cr")) {
-                       options->lftocr ^= 1; return 0;
+                   options->lftocr ^= 1; return 0;
                } else {
-                       return 1;
+                   return 1;
                }
        case 'c':
                if (!strcmp(str, "cr-in-lf")) {
-                       options->crinlf ^= 1; return 0;
+                   options->crinlf ^= 1; return 0;
                } else if (!strcmp(str, "cr-to-lf")) {
-                       options->crtolf ^= 1; return 0;
+                   options->crtolf ^= 1; return 0;
                } else {
-                       return 1;
+                   return 1;
                }
        case 'n':
                if (!strcmp(str, "no-lf")) {
-                       options->nolf ^= 1; return 0;
+                   options->nolf ^= 1; return 0;
                } else if (!strcmp(str, "no-cr")) {
-                       options->nocr ^= 1; return 0;
+                   options->nocr ^= 1; return 0;
                } else {
-                       return 1;
+                   return 1;
                }
        default:
                return 1;
@@ -402,11 +400,11 @@ lsbmask(unsigned int n)
 }
 
 inline int
-termvalid(const term_struct *term)
+termvalid(const TermStruct *term)
 {
-       for (size_t i = 0; i < sizeof(term_struct); i++)
-               if (((char*)term)[i] != 0)
-                       return 1;
+       for (size_t i = 0; i < sizeof(TermStruct); i++)
+               if (((char*)term)[i] != 0)
+                   return 1;
 
        return 0;
 }
@@ -416,6 +414,7 @@ writeport(void *unused)
 {
        Sizes msizes;
        struct timespec ts;
+       int escape = 0;
 
        ts.tv_sec = swritedelay;
        ts.tv_nsec = nswritedelay;
@@ -431,46 +430,45 @@ writeport(void *unused)
                die(1, "buffer allocation failed\n");
        if (scratchw == NULL)
                die(1, "scratch buffer allocation failed\n");
-       
-       int escape = 0;
 
        for (;;) {
                ssize_t inln = read(STDIN_FILENO, writebuff, wbuffsz - 1);
-               if (inln > 0) { 
-                       if (escape) {
-                               getcmd(escape);
-                               escape = 0;
-                               inln = 0;
-                       }
-                       if (writebuff[0] == escapechar) {
-                               if (inln > 1)
-                                       getcmd(escape); 
-                               else 
-                                       escape = 1;
-                               inln = 0;
-                       }
-
-                       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, &msizes, &lfincrargs);
-                       
-                       if (inln > 1) {
-                               for (int i = 0; i <= inln; i++) {
-                                       rwc -= write(fd, &writebuff[i], 1);
-                                       nanosleep(&wts, NULL);
-                               }
-
-                       } else {
-                               rwc -= write(fd, writebuff, inln);
-                       }
+               if (inln > 0) {
+                   if (escape) {
+                       getcmd(escape);
+                       escape = 0;
+                       inln = 0;
+                   }
+                   if (writebuff[0] == escapechar) {
+                       if (inln > 1)
+                           getcmd(escape);
+                       else 
+                           escape = 1;
+                       inln = 0;
+                   }
+
+                   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, &msizes,
+                                      &lfincrargs);
+
+                   if (inln > 1) {
+                       for (int i = 0; i <= inln; i++) {
+                               rwc -= write(fd, &writebuff[i], 1);
+                               nanosleep(&wts, NULL);
+                       }
+
+                   } else {
+                       rwc -= write(fd, writebuff, inln);
+                   }
 
                } else if (inln == 0 && !interactive) {
-                       break;
+                   break;
                }
                nanosleep(&ts, NULL);
        }
@@ -508,16 +506,18 @@ readport(void *unused)
        for (;;) {
                ssize_t outln = read(fd, readbuff, rbuffsz - 1);
                if (outln > 0) {
-                       if (itropts.nocr)
-                               outln = rmchar(readbuff, outln, scratchr, &nocrargs);
-                       if (itropts.nolf)
-                               outln = rmchar(readbuff, outln, scratchr, &nolfargs);
-                       if (itropts.crinlf)
-                               outln = addchar(readbuff, outln, scratchr, &msizes, &crinlfargs);
-                       if (itropts.lfincr)
-                               outln = addchar(readbuff, outln, scratchr, &msizes, &lfincrargs);
-
-                       rwc += write(STDOUT_FILENO, readbuff, outln);
+                   if (itropts.nocr)
+                       outln = rmchar(readbuff, outln, scratchr, &nocrargs);
+                   if (itropts.nolf)
+                       outln = rmchar(readbuff, outln, scratchr, &nolfargs);
+                   if (itropts.crinlf)
+                       outln = addchar(readbuff, outln, scratchr, &msizes,
+                                       &crinlfargs);
+                   if (itropts.lfincr)
+                       outln = addchar(readbuff, outln, scratchr, &msizes,
+                                       &lfincrargs);
+
+                   rwc += write(STDOUT_FILENO, readbuff, outln);
                }
                nanosleep(&ts, NULL);
        }
@@ -531,11 +531,12 @@ replacechar(char *buff, ssize_t size, const Args *args)
 {
        for (int i = 0; i < size; i++)
                if (buff[i] == args->find)
-                       buff[i] = args->input;
+                   buff[i] = args->input;
 }
 
 inline ssize_t
-addchar(char *buff, ssize_t size, int *scratch, const Sizes *sizes, const Args *args)
+addchar(char *buff, ssize_t size, int *scratch, const Sizes *sizes,
+        const Args *args)
 {
        int to, c;
        c = 0;
@@ -544,11 +545,11 @@ addchar(char *buff, ssize_t size, int *scratch, const Sizes *sizes, const Args *
 
        for (int i = 0; i < size; i++) {
                if (buff[i] == args->find) {
-                       scratch[c] = i;
-                       c++;
+                   scratch[c] = i;
+                   c++;
                }
                if (c >= sizes->sizesm)
-                       break;
+                   break;
        }
        if (!c)
                return(size);
@@ -574,8 +575,8 @@ 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;
-                       c++;
+                   scratch[c] = i;
+                   c++;
                }
        }
        if (!c)
@@ -594,49 +595,47 @@ void
 eninter(void)
 {
        if (interactive) {
-               if (pfd < 0)
-                       pfd = openparent();
-
                if (!canonical)
-                       newterm.c_lflag &= ~ECHO;
+                   newterm.c_lflag &= ~ECHO;
                if (!half)
-                       newterm.c_lflag &= ~ICANON;
+                   newterm.c_lflag &= ~ICANON;
 
                if (soft)
-                       newterm.c_iflag |= IXONXOFF;
+                   newterm.c_iflag |= IXONXOFF;
 
                newterm.c_iflag |= INLCR;
                newterm.c_cc[VMIN] = minchars;
                newterm.c_cc[VTIME] = 0;
-               newterm.c_cc[VINTR] = newterm.c_cc[VSUSP]\
-                       = newterm.c_cc[VQUIT] = newterm.c_cc[VLNEXT]\
-                       = newterm.c_cc[VDISCARD] = _POSIX_VDISABLE;
+               newterm.c_cc[VINTR] = newterm.c_cc[VSUSP]
+                   = newterm.c_cc[VQUIT] = newterm.c_cc[VLNEXT]
+                   = newterm.c_cc[VDISCARD] = _POSIX_VDISABLE;
                                
                #ifdef VDSUSP
                 newterm.c_cc[VDSUSP] = _POSIX_VDISABLE;
                #endif
 
                if (backspace)
-                       bsargs.input = BS;
+                   bsargs.input = BS;
                else
-                       bsargs.input = DEL;
+                   bsargs.input = DEL;
 
                bsargs.find = origterm.c_cc[VERASE];
                
                if (settermattr(pfd, &newterm) < 0)
-                       die(1, "failed to set terminal attributes\n");
+                   die(1, "failed to set terminal attributes\n");
        }
        return;
 }
 
 void
-enechocan(void)
+enusrecho(void)
 {
        if ((!half || !canonical) && interactive) {
                newterm.c_lflag |= ECHO;
                newterm.c_lflag |= ICANON;
                if (settermattr(pfd, &newterm) < 0)
-                       fprintf(stderr, "failed to enable local echo and/or canonical mode\n");
+                   fprintf(stderr,
+                           "failed to enable local echo for user input\n");
        }
        return;
 }
@@ -645,6 +644,7 @@ void
 getcmd(int escape)
 {
        Sizes msizes;
+       CRLFOpt *toptptr;
        char cmdchar;
        char ttr[64];
        unsigned int tspd;
@@ -652,11 +652,6 @@ getcmd(int escape)
        msizes.sizesm = scratchwsz;
        msizes.sizebm = wbuffsz;
 
-       if (isatty(STDIN_FILENO))
-               interactive = 1;
-
-       eninter();
-
        if (escape)
                cmdchar = writebuff[0];
        else
@@ -668,116 +663,114 @@ getcmd(int escape)
                die(0,"\n[EOT]\n");
        case 'b':
                if (backspace)
-                       bsargs.input = DEL;
+                   bsargs.input = DEL;
                else
-                       bsargs.input = BS;
+                   bsargs.input = BS;
                backspace ^= 1;
                break;
        case 'h':
                if (half)
-                       newterm.c_lflag &= ~ECHO;
+                   newterm.c_lflag &= ~ECHO;
                else
-                       newterm.c_lflag |= ECHO;
-               half ^= 1;
+                   newterm.c_lflag |= ECHO;
                if (settermattr(pfd, &newterm) < 0)
-                       die(1, "failed to set terminal attributes\n");
+                   die(1, "failed to set terminal attributes\n");
+               else
+                   half ^= 1;
                break;
        case 'c':
                if (canonical)
-                       newterm.c_lflag &= ~ICANON;
+                   newterm.c_lflag &= ~ICANON;
                else
-                       newterm.c_lflag |= ICANON;
-               canonical ^= 1;
+                   newterm.c_lflag |= ICANON;
                if (settermattr(pfd, &newterm) < 0)
-                       die(1, "failed to set terminal attributes\n");
+                   die(1, "failed to set terminal attributes\n");
+               else
+                   canonical ^= 1;
                break;
        case 'w':
-               enechocan();
+               enusrecho();
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       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);
-                                       if (tropts.nolf)
-                                               frln = rmchar(writebuff, frln, scratchw, &nolfargs);
-                                       if (tropts.lfincr)
-                                               frln = addchar(writebuff, frln, scratchw, &msizes, &lfincrargs);
+                   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);
+                           if (tropts.nolf)
+                               frln = rmchar(writebuff, frln, scratchw,
+                                             &nolfargs);
+                           if (tropts.lfincr)
+                               frln = addchar(writebuff, frln, scratchw,
+                                              &msizes, &lfincrargs);
        
-                                       rwc -= write(fd, &writebuff[i], 1);
-                                       nanosleep(&wts, NULL);
-                               }
-                       }
+                           rwc -= write(fd, &writebuff[i], 1);
+                           nanosleep(&wts, NULL);
+                       }
+                   }
                }
                goto finish;
        case 's':
-               enechocan();
+               enusrecho();
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &nolfargs);
-                       tspd = strtoui(ttr, 0);
-                       if (tspd != uintmax) {
-                               ospeed = ispeed = tspd;
-                               settermspd(ispeed, ospeed, &cntrl);
-                               if (settermattr(fd, &cntrl) < 0)
-                                       fprintf(stderr, "failed to set baudrate "
-                                                       "[RX:%u | TX:%u]\n", ispeed, ospeed);
-                       } else {
-                               fprintf(stderr, "invalid speed: %s\n", ttr);
-                       }
+                   replacechar(ttr, 63, &nolfargs);
+                   tspd = strtoui(ttr, 0);
+                   if (tspd != uintmax) {
+                       ospeed = ispeed = tspd;
+                       settermspd(ispeed, ospeed, &cntrl);
+                       if (settermattr(fd, &cntrl) < 0)
+                           fprintf(stderr, "failed to set baudrate "
+                                   "[RX:%u | TX:%u]\n", ispeed, ospeed);
+                   } else {
+                       fprintf(stderr, "invalid speed: %s\n", ttr);
+                   }
                }
                goto finish;
        case 'd':
-               enechocan();
-               if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &nolfargs);
-                       chardelay = strtoui(ttr, 0);
-                       if (chardelay != uintmax) {
-                               wts.tv_sec = 0;
-                               wts.tv_nsec = chardelay;
-                       } else {
-                               fprintf(stderr, "invalid delay: %s\n", ttr);
-                       }
-               }
-               goto finish;
-       case 't':
-               enechocan();
-               fprintf(stderr, "additional output translation option: ");
+               enusrecho();
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &nolfargs);
-                       if (chcktropts(&tropts, ttr)) {
-                               fprintf(stderr, "invalid output translation option: %s\n", optarg);
-                               goto finish;
-                       }
-                       if (settropts())
-                               fprintf(stderr, "could not set new options\n");         
+                   replacechar(ttr, 63, &nolfargs);
+                   chardelay = strtoui(ttr, 0);
+                   if (chardelay != uintmax) {
+                       wts.tv_sec = 0;
+                       wts.tv_nsec = chardelay;
+                   } else {
+                       fprintf(stderr, "invalid delay: %s\n", ttr);
+                   }
                }
                goto finish;
+       case 't': /* FALLTHROUGH */
        case 'T':
-               enechocan();
-               printf("additional input translation option: ");
+               enusrecho();
+               toptptr = (cmdchar == 't') ? &tropts : &itropts;
+               fprintf(stderr, "additional translation option: ");
                if (fgets(ttr, sizeof(ttr), stdin) != NULL) {
-                       replacechar(ttr, 63, &nolfargs);
-                       if (chcktropts(&itropts, ttr)) {
-                               fprintf(stderr, "invalid input translation option: %s\n", optarg);
-                               goto finish;
-                       }       
-                       if (settropts())
-                               fprintf(stderr, "could not set new options\n"); 
+                   replacechar(ttr, 63, &nolfargs);
+                   if (chcktropts(toptptr, ttr)) {
+                       fprintf(stderr,
+                               "invalid translation option: %s\n",
+                               optarg);
+
+                       goto finish;
+                   }   
+                   if (settropts())
+                       fprintf(stderr, "could not set new options\n");
                }
                finish:
                if (!half && interactive)
-                       newterm.c_lflag &= ~ECHO;
+                   newterm.c_lflag &= ~ECHO;
                if (!canonical && interactive)
-                       newterm.c_lflag &= ~ICANON;
+                   newterm.c_lflag &= ~ICANON;
                if (settermattr(pfd, &newterm) < 0)
-                       fprintf(stderr, "failed to restore echo and/or canonical mode\n");
+                   fprintf(stderr,
+                           "failed to restore echo and/or canonical mode\n");
                break;
        case 'p':;
                int st;
@@ -786,19 +779,19 @@ getcmd(int escape)
                ts.tv_nsec = nspulsedelay;
 
                if (ioctl(fd, TIOCMGET, &st) < 0) {
-                       fprintf(stderr, "failed to get port status\n");
-                       break;
+                   fprintf(stderr, "failed to get port status\n");
+                   break;
                }
                st ^= TIOCM_DTR;
                if (ioctl(fd, TIOCMSET, &st) < 0) {
-                       fprintf(stderr, "failed to set DTR [assertion]\n");
-                       break;
+                   fprintf(stderr, "failed to set DTR [assertion]\n");
+                   break;
                }
                nanosleep(&ts, NULL);
                
                st ^= TIOCM_DTR;
-               if (ioctl(fd, TIOCMSET, &st) < 0) 
-                       fprintf(stderr, "failed to set DTR [negation]\n");
+               if (ioctl(fd, TIOCMSET, &st) < 0)
+                   fprintf(stderr, "failed to set DTR [negation]\n");
                break;
        case BS: /* FALLTHROUGH */
        case DEL:
@@ -822,17 +815,18 @@ die(int code, const char *msg, ...)
 {
        va_list fpa;
 
+       if (termvalid(&origterm))
+               settermattr(pfd, &origterm);
+
        while (rwc > 0) {
                int t = rwc;
                nanosleep(&wts, NULL);
                if (t == rwc) break;
        }
 
-       if (termvalid(&origterm))
-               settermattr(pfd, &origterm);
-       if (pfd != -1)
+       if (pfd < 0)
                close(pfd);
-       if (fd != -1)
+       if (fd < 0)
                close(fd);
 
        if (writebuff)
@@ -862,13 +856,17 @@ main(int argc, char *argv[])
        oind = rxspdset = devset = 0;
 
        for (int i = 1; i < argc; i++) {
-               if (argv[i][0] == '-' && argv[i][1] >= '0' && argv[i][1] <= '9') {
-                       if (asprintf(&t, "-s%s", argv[i] + 1) == -1) {
-                               fprintf(stderr, "%s: cannot convert -# to -s#\n", argv[0]);
-                               break;
-                       } else {
-                               argv[i] = t;
-                       }
+               if (argv[i][0] == '-' && argv[i][1] >= '0' &&
+                   argv[i][1] <= '9') {
+                   if (asprintf(&t, "-s%s", argv[i] + 1) == -1) {
+                       fprintf(stderr,
+                               "%s: cannot convert -# to -s#\n",
+                               argv[0]);
+
+                       break;
+                   } else {
+                       argv[i] = t;
+                   }
                }
        }
 
@@ -894,9 +892,10 @@ main(int argc, char *argv[])
                {NULL, 0, NULL, 0}
        };
         
-       while ((c = getopt_long(argc, argv, "D:T:d: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)) >= 0) {
                switch (c) {
-               case 0: 
+               case 0:
                        break;
                case 'b':
                        backspace ^= 1; break;
@@ -911,18 +910,25 @@ main(int argc, char *argv[])
                case 'd':
                        tl = strtol(optarg, &endptr, 10);
                        if (errno != 0 || *endptr != '\0' || tl < 0) {
-                               fprintf(stderr, "%s: invalid character delay: %s\n", argv[0],optarg);
-                               goto ustusage;
+                           fprintf(stderr,
+                               "%s: invalid character delay: %s\n",
+                               argv[0], optarg);
+
+                           goto ustusage;
                        } else {
-                               chardelay = tl;
+                           chardelay = tl;
                        }
                        break;
                case 'D':
-                       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;  
+                       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 {
-                               datab = optarg[0];
+                           datab = optarg[0];
                        }
                        break;
                case 'e':
@@ -935,70 +941,86 @@ main(int argc, char *argv[])
                case 's':
                        tui = strtoui(optarg, 1);
                        if (tui == uintmax) {
-                               fprintf(stderr, "%s: invalid speed: %s\n", argv[0], optarg);
-                               goto ustusage;
+                           fprintf(stderr,
+                                   "%s: invalid speed: %s\n",
+                                   argv[0], optarg);
+
+                           goto ustusage;
                        }
                        if (c == 'i') {
-                               ispeed = tui; rxspdset = 1;
+                           ispeed = tui; rxspdset = 1;
                        } else {
-                               ospeed = tui;
-                               ispeed = rxspdset ? ispeed : ospeed;
+                           ospeed = tui;
+                           ispeed = rxspdset ? ispeed : ospeed;
                        }
                        break;
                case 'S':
                        stopb ^= 1; break;
                case 'l':
                        if (devset) {
-                               fprintf(stderr, "%s: cannot specify multiple devices\n", argv[0]);
-                               goto ustusage;
+                           fprintf(stderr,
+                               "%s: cannot specify multiple devices\n",
+                               argv[0]);
+
+                           goto ustusage;
                        }
                        if (strlen(optarg) > 58) {
-                               fprintf(stderr, "%s: device name too long\n", argv[0]);
-                               goto ustusage;
+                           fprintf(stderr, "%s: device name too long\n", argv[0]);
+                           goto ustusage;
                        }
                        if (strchr(optarg, '/')) {
-                               strcpy(line, optarg);
-                               devset = 1;
+                           strcpy(line, optarg);
+                           devset = 1;
                        } else {
-                               sprintf(line, "/dev/%s", optarg);
-                               devset = 1;
+                           sprintf(line, "/dev/%s", optarg);
+                           devset = 1;
                        }
                        break;
                case 'm':
                        tui = strtoui(optarg, 1);
                        if (tui == uintmax) {
-                               fprintf(stderr, "%s: invalid number of characters: %s\n", argv[0], optarg);
-                               goto ustusage;
+                           fprintf(stderr,
+                               "%s: invalid number of characters: %s\n",
+                               argv[0], optarg);
+
+                               goto ustusage;
                        }
                        minchars = tui;
                        break;
                case 't':
-                       if (chcktropts(&tropts, optarg))        {
-                               fprintf(stderr, "%s: invalid output translation option: %s\n", argv[0], optarg);
-                               goto ustusage;
+                       if (chcktropts(&tropts, optarg)) {
+                           fprintf(stderr,
+                               "%s: invalid output translation option: %s\n",
+                               argv[0], optarg);
+
+                               goto ustusage;
                        }
                        break;
                case 'T':
                        if (chcktropts(&itropts, optarg)) {
-                               fprintf(stderr, "%s: invalid input translation option: %s\n", argv[0], optarg);
-                               goto ustusage;
+                           fprintf(stderr,
+                               "%s: invalid input translation option: %s\n",
+                               argv[0], optarg);
+
+                               goto ustusage;
                        }
                        break;
                case 'v':
                        verbose ^= 1; break;
                default:
                ustusage:
-                       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-rts-cts | -R]"
-                                       " [--hardware-dtr-dsr | -r] [--software | -X]\n"
-                                       "           [--delay | -d #] [--min-chars | -m #]"
-                                       " [--canonical | -c] [--echo | -h]\n"
-                                       "           [--translation | -t option]"
-                                       " [--input-translation | -T option]\n"
-                                       "           [--verbose | -v] [--backspace | -b]\n",
-                                       argv[0]);
+                       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-rts-cts | -R] "
+                              "[--hardware-dtr-dsr | -r] [--software | -X]\n"
+                              "           [--min-chars | -m #] [--echo | -h] "
+                              "[--canonical | -c] [--delay | -d #]\n"
+                              "           [--translation | -t option] "
+                              "[--input-translation | -T option]\n"
+                              "           [--verbose | -v] "
+                              "[--backspace | -b]\n", argv[0]);
                        break;
                }
        }
@@ -1017,6 +1039,13 @@ main(int argc, char *argv[])
        fd = openport();
        if (interactive) pfd = openparent();
 
+       #ifdef __OpenBSD__
+        if (pledge("stdio rpath tty", NULL) < 0) {
+                 perror("pledge");
+                 die(1, "pledge failed, exiting now\n");
+        }
+       #endif
+
        pthread_t readthread, writethread;
        pthread_create(&writethread, NULL, writeport, NULL);
        pthread_create(&readthread, NULL, readport, NULL);