summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2016-06-14 22:33:07 -0700
committerMichael Forney <mforney@mforney.org>2016-06-14 22:33:07 -0700
commitbe5cf8fe0349dabeb74cf350c0bad14cdfc949cc (patch)
tree0f634e1ea359f97841aa6ab34a9200a246509ed0
parent05955bdf3fdc0f1a9b3be3f00a0d5ed8bd39267b (diff)
ubase: Add stty from suckless mailing list
-rw-r--r--core/ubase/gen.rc1
-rw-r--r--core/ubase/patch/0002-mount-Don-t-pass-no-auto-to-kernel.patch2
-rw-r--r--core/ubase/patch/0003-Add-stty-1.patch811
-rw-r--r--core/ubase/patch/0004-stty-cleaner-output-when-no-arguments-are-used.patch96
-rw-r--r--core/ubase/patch/0005-stty-fix-casting-bug.patch35
-rw-r--r--core/ubase/patch/0006-stty-add-symbolic-values-for-line-disciplines.patch139
-rw-r--r--core/ubase/patch/0007-stty-simplify.patch49
-rw-r--r--core/ubase/patch/0008-stty-Fix-indentation.patch79
-rw-r--r--core/ubase/patch/0009-stty-Fix-build-with-musl-libc.patch53
9 files changed, 1264 insertions, 1 deletions
diff --git a/core/ubase/gen.rc b/core/ubase/gen.rc
index edcdf828..229ee455 100644
--- a/core/ubase/gen.rc
+++ b/core/ubase/gen.rc
@@ -78,6 +78,7 @@ x readahead 8
x respawn 1
x rmmod 8
x stat 1
+x stty
x -m 4755 su 1
x swaplabel 8
x swapoff 8
diff --git a/core/ubase/patch/0002-mount-Don-t-pass-no-auto-to-kernel.patch b/core/ubase/patch/0002-mount-Don-t-pass-no-auto-to-kernel.patch
index f524e07a..bddcb0fb 100644
--- a/core/ubase/patch/0002-mount-Don-t-pass-no-auto-to-kernel.patch
+++ b/core/ubase/patch/0002-mount-Don-t-pass-no-auto-to-kernel.patch
@@ -1,4 +1,4 @@
-From d893d74e564d3f7fcaf9dfcdd485ebad0f01b602 Mon Sep 17 00:00:00 2001
+From 8dee43a5ff31bbe2b463ca66b168202501a14a92 Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Sun, 12 Jun 2016 20:51:43 -0700
Subject: [PATCH] mount: Don't pass {,no}auto to kernel
diff --git a/core/ubase/patch/0003-Add-stty-1.patch b/core/ubase/patch/0003-Add-stty-1.patch
new file mode 100644
index 00000000..7f9876a6
--- /dev/null
+++ b/core/ubase/patch/0003-Add-stty-1.patch
@@ -0,0 +1,811 @@
+From a5fa7dc291bf970a05e113434cd847e03d61e826 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Mattias=20Andr=C3=A9e?= <maandree@kth.se>
+Date: Mon, 28 Mar 2016 18:52:07 +0200
+Subject: [PATCH] Add stty(1)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Mattias Andrée <maandree@kth.se>
+---
+ Makefile | 1 +
+ TODO | 1 +
+ stty.c | 762 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 764 insertions(+)
+ create mode 100644 stty.c
+
+diff --git a/Makefile b/Makefile
+index 453607c..4b872ae 100644
+--- a/Makefile
++++ b/Makefile
+@@ -75,6 +75,7 @@ BIN = \
+ respawn \
+ rmmod \
+ stat \
++ stty \
+ su \
+ swaplabel \
+ swapoff \
+diff --git a/TODO b/TODO
+index 21f5c20..5cdc351 100644
+--- a/TODO
++++ b/TODO
+@@ -23,6 +23,7 @@ rfkill
+ rmgroup
+ rmuser
+ setcap
++stty manpage
+ tabs
+ taskset
+ top
+diff --git a/stty.c b/stty.c
+new file mode 100644
+index 0000000..c65748a
+--- /dev/null
++++ b/stty.c
+@@ -0,0 +1,762 @@
++/* See LICENSE file for copyright and license details. */
++#include <ctype.h>
++#include <errno.h>
++#include <limits.h>
++#include <stdarg.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/ioctl.h>
++#include <termios.h>
++#include <unistd.h>
++
++#include "util.h"
++
++/*
++ * Petty POSIX violations:
++ *
++ * - XBD 12.2 is not honoured precisely. This is for
++ * convenience and compatibility with other implementations.
++ */
++
++#define CC_MAX 255
++
++static int output_size_requested = 0;
++static int output_speed_requested = 0;
++static int drain_requested = 1;
++
++static void sane(int, struct termios *);
++static void setwinsize(long, long);
++static void ispeed(char *, struct termios *);
++static void ospeed(char *, struct termios *);
++
++static void
++raw(int unset, struct termios *m)
++{
++ if (!unset) {
++ m->c_iflag = 0;
++ m->c_lflag &= ~XCASE;
++ m->c_cc[VMIN] = 1;
++ m->c_cc[VTIME] = 0;
++ } else {
++ m->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
++ }
++}
++
++static void
++evenp(int unset, struct termios *m)
++{
++ m->c_oflag &= ~CSIZE;
++ m->c_oflag &= ~(unset ? PARENB : PARODD);
++ m->c_oflag |= unset ? CS8 : (CS7 | PARENB);
++}
++
++
++static void
++dec(int unset, struct termios *m)
++{
++ m->c_cc[VINTR] = CINTR;
++ m->c_cc[VKILL] = CKILL;
++ m->c_cc[VERASE] = CERASE;
++ (void) unset;
++}
++
++static void
++ek(int unset, struct termios *m)
++{
++ m->c_cc[VKILL] = CKILL;
++ m->c_cc[VERASE] = CERASE;
++ (void) unset;
++}
++
++static void
++nl(int unset, struct termios *m)
++{
++ if (unset) {
++ m->c_iflag &= ~(INLCR | IGNCR);
++ m->c_oflag &= ~(OCRNL | ONLRET);
++ }
++}
++
++static void
++oddp(int unset, struct termios *m)
++{
++ m->c_oflag &= ~CSIZE;
++ m->c_oflag &= ~(unset ? PARENB : 0);
++ m->c_oflag |= unset ? CS8 : (CS7 | PARODD | PARENB);
++}
++
++static void drain(int unset, struct termios *m) { drain_requested = !unset; (void) m; }
++static void cooked(int unset, struct termios *m) { raw(!unset, m); }
++static void pass8(int unset, struct termios *m) { m->c_cflag &= ~CSIZE, m->c_cflag |= unset ? CS7 : CS8; }
++static void size(int unset, struct termios *m) { output_size_requested = 1; (void) m; (void) unset; }
++static void speed(int unset, struct termios *m) { output_speed_requested = 1; (void) m; (void) unset; }
++static void tabs(int unset, struct termios *m) { m->c_oflag &= ~TABDLY, m->c_oflag |= unset ? TAB3 : TAB0; }
++static void cols(char *arg, struct termios *m) { setwinsize(-1, estrtonum(arg, 0, USHRT_MAX)); (void) m; }
++static void line(char *arg, struct termios *m) { m->c_line = estrtonum(arg, 0, 255); }
++static void min(char *arg, struct termios *m) { m->c_cc[VMIN] = estrtonum(arg, 0, CC_MAX); }
++static void rows(char *arg, struct termios *m) { setwinsize(estrtonum(arg, 0, USHRT_MAX), -1); (void) m; }
++static void stime(char *arg, struct termios *m) { m->c_cc[VTIME] = estrtonum(arg, 0, CC_MAX); }
++
++enum type { CTRL, IN, OUT, LOCAL, COMB, SPEC };
++enum {
++ BOOL = 1,
++ DUP = 2,
++ SANE = 4,
++ INSANE = 8,
++ CBREAK = 16,
++ DECCTLQ = 32,
++ LCASE = 64,
++ PASS8 = 128,
++ LITOUT = 256,
++ CRT = 1024,
++ DEC = 2048,
++ NL = 4096,
++ COOKED = 8192
++};
++
++struct mode {
++ const char *op;
++ enum type type;
++ tcflag_t set;
++ tcflag_t clear;
++ void (*fun)(int, struct termios *);
++ int flags;
++};
++
++struct key {
++ const char *op;
++ size_t index;
++ cc_t sanevalue;
++};
++
++struct intvalued {
++ const char *op;
++ void (*fun)(char *, struct termios *);
++};
++
++struct speed {
++ const char *str;
++ speed_t speed;
++};
++
++static const struct mode modes[] = {
++ {"clocal", CTRL, CLOCAL, 0, 0, BOOL},
++ {"cmspar", CTRL, CMSPAR, 0, 0, BOOL},
++ {"cread", CTRL, CREAD, 0, 0, BOOL | SANE},
++ {"crtscts", CTRL, CRTSCTS, 0, 0, BOOL},
++ {"cs5", CTRL, CS5, CSIZE, 0, 0},
++ {"cs6", CTRL, CS6, CSIZE, 0, 0},
++ {"cs7", CTRL, CS7, CSIZE, 0, 0},
++ {"cs8", CTRL, CS8, CSIZE, 0, 0},
++ {"cstopb", CTRL, CSTOPB, 0, 0, BOOL},
++ {"hup", CTRL, HUPCL, 0, 0, BOOL | DUP},
++ {"hupcl", CTRL, HUPCL, 0, 0, BOOL},
++ {"parenb", CTRL, PARENB, 0, 0, BOOL | PASS8 | LITOUT},
++ {"parodd", CTRL, PARODD, 0, 0, BOOL},
++
++ {"brkint", IN, BRKINT, 0, 0, BOOL | SANE},
++ {"icrnl", IN, ICRNL, 0, 0, BOOL | SANE | NL},
++ {"ignbrk", IN, IGNBRK, 0, 0, BOOL | INSANE},
++ {"igncr", IN, IGNCR, 0, 0, BOOL | INSANE},
++ {"ignpar", IN, IGNPAR, 0, 0, BOOL},
++ {"imaxbel", IN, IMAXBEL, 0, 0, BOOL | SANE},
++ {"inlcr", IN, INLCR, 0, 0, BOOL | INSANE},
++ {"inpck", IN, INPCK, 0, 0, BOOL},
++ {"istrip", IN, ISTRIP, 0, 0, BOOL | PASS8 | LITOUT},
++ {"iuclc", IN, IUCLC, 0, 0, BOOL | INSANE | LCASE},
++ {"iutf8", IN, IUTF8, 0, 0, BOOL | SANE},
++ {"ixany", IN, IXANY, 0, 0, BOOL | INSANE | DECCTLQ},
++ {"ixoff", IN, IXOFF, 0, 0, BOOL | INSANE},
++ {"ixon", IN, IXON, 0, 0, BOOL},
++ {"parmrk", IN, PARMRK, 0, 0, BOOL},
++ {"tandem", IN, IXOFF, 0, 0, BOOL | DUP},
++
++ {"bs0", OUT, BS0, BSDLY, 0, SANE},
++ {"bs1", OUT, BS1, BSDLY, 0, INSANE},
++ {"cr0", OUT, CR0, CRDLY, 0, SANE},
++ {"cr1", OUT, CR1, CRDLY, 0, INSANE},
++ {"cr2", OUT, CR2, CRDLY, 0, INSANE},
++ {"cr3", OUT, CR3, CRDLY, 0, INSANE},
++ {"ff0", OUT, FF0, FFDLY, 0, SANE},
++ {"ff1", OUT, FF1, FFDLY, 0, INSANE},
++ {"nl0", OUT, NL0, NLDLY, 0, SANE},
++ {"nl1", OUT, NL1, NLDLY, 0, INSANE},
++ {"ocrnl", OUT, OCRNL, 0, 0, BOOL | INSANE},
++ {"ofdel", OUT, OFDEL, 0, 0, BOOL | INSANE},
++ {"ofill", OUT, OFILL, 0, 0, BOOL | INSANE},
++ {"olcuc", OUT, OLCUC, 0, 0, BOOL | INSANE | LCASE},
++ {"onlcr", OUT, ONLCR, 0, 0, BOOL | SANE | NL},
++ {"onlret", OUT, ONLRET, 0, 0, BOOL | INSANE},
++ {"onocr", OUT, ONOCR, 0, 0, BOOL | INSANE},
++ {"opost", OUT, OPOST, 0, 0, BOOL | SANE | LITOUT | COOKED},
++ {"tab0", OUT, TAB0, TABDLY, 0, SANE},
++ {"tab1", OUT, TAB1, TABDLY, 0, INSANE},
++ {"tab2", OUT, TAB2, TABDLY, 0, INSANE},
++ {"tab3", OUT, TAB3, TABDLY, 0, INSANE},
++ {"vt0", OUT, VT0, VTDLY, 0, SANE},
++ {"vt1", OUT, VT1, VTDLY, 0, INSANE},
++
++ {"crterase", LOCAL, ECHOE, 0, 0, BOOL | DUP},
++ {"crtkill", LOCAL, ECHOKE, 0, 0, BOOL | DUP},
++ {"ctlecho", LOCAL, ECHOCTL, 0, 0, BOOL | DUP},
++ {"echo", LOCAL, ECHO, 0, 0, BOOL | SANE},
++ {"echoctl", LOCAL, ECHOCTL, 0, 0, BOOL | SANE | CRT | DEC},
++ {"echoe", LOCAL, ECHOE, 0, 0, BOOL | SANE | CRT | DEC},
++ {"echok", LOCAL, ECHOK, 0, 0, BOOL | SANE},
++ {"echoke", LOCAL, ECHOKE, 0, 0, BOOL | SANE | CRT | DEC},
++ {"echonl", LOCAL, ECHONL, 0, 0, BOOL | INSANE},
++ {"echoprt", LOCAL, ECHOPRT, 0, 0, BOOL | INSANE},
++ {"extproc", LOCAL, EXTPROC, 0, 0, BOOL | INSANE},
++ {"flusho", LOCAL, FLUSHO, 0, 0, BOOL | INSANE},
++ {"icanon", LOCAL, ICANON, 0, 0, BOOL | SANE | CBREAK | COOKED},
++ {"iexten", LOCAL, IEXTEN, 0, 0, BOOL | SANE},
++ {"isig", LOCAL, ISIG, 0, 0, BOOL | SANE | COOKED},
++ {"noflsh", LOCAL, NOFLSH, 0, 0, BOOL | INSANE},
++ {"prterase", LOCAL, ECHOPRT, 0, 0, BOOL | DUP},
++ {"tostop", LOCAL, TOSTOP, 0, 0, BOOL | INSANE},
++ {"xcase", LOCAL, XCASE, 0, 0, BOOL | INSANE | LCASE},
++
++ {"cbreak", COMB, 0, CBREAK, 0, BOOL | DUP},
++ {"cooked", COMB, COOKED, 0, cooked, BOOL | DUP},
++ {"crt", COMB, CRT, 0, 0, DUP},
++ {"dec", COMB, DEC, DECCTLQ, dec, DUP},
++ {"decctlq", COMB, 0, DECCTLQ, 0, BOOL | DUP},
++ {"ek", COMB, 0, 0, ek, DUP},
++ {"evenp", COMB, 0, 0, evenp, BOOL | DUP},
++ {"LCASE", COMB, LCASE, 0, 0, BOOL | DUP},
++ {"lcase", COMB, LCASE, 0, 0, BOOL | DUP},
++ {"litout", COMB, 0, LITOUT, pass8, BOOL | DUP},
++ {"nl", COMB, 0, NL, nl, BOOL | DUP},
++ {"oddp", COMB, 0, 0, oddp, BOOL | DUP},
++ {"parity", COMB, 0, 0, evenp, BOOL | DUP},
++ {"pass8", COMB, 0, PASS8, pass8, BOOL | DUP},
++ {"raw", COMB, 0, COOKED, raw, BOOL | DUP},
++ {"sane", COMB, SANE, INSANE, sane, DUP},
++ {"tabs", COMB, 0, 0, tabs, BOOL | DUP},
++
++ {"size", SPEC, 0, 0, size, DUP},
++ {"speed", SPEC, 0, 0, speed, DUP},
++ {"drain", SPEC, 0, 0, drain, BOOL | DUP},
++
++ {0, 0, 0, 0, 0, 0}
++};
++
++static const struct key keys[] = {
++ {"discard", VDISCARD, CDISCARD},
++ {"eof", VEOF, CEOF},
++ {"eol", VEOL, CEOL},
++ {"eol2", VEOL2, _POSIX_VDISABLE},
++ {"erase", VERASE, CERASE},
++ {"intr", VINTR, CINTR},
++ {"kill", VKILL, CKILL},
++ {"lnext", VLNEXT, CLNEXT},
++ {"quit", VQUIT, CQUIT},
++ {"rprnt", VREPRINT, CRPRNT},
++ {"start", VSTART, CSTART},
++ {"stop", VSTOP, CSTOP},
++ {"susp", VSUSP, CSUSP},
++ {"swtch", VSWTC, _POSIX_VDISABLE},
++ {"werase", VWERASE, CWERASE},
++ {0, 0, 0}
++};
++
++static const struct intvalued ints[] = {
++ {"cols", cols},
++ {"columns", cols},
++ {"line", line},
++ {"min", min},
++ {"rows", rows},
++ {"time", stime},
++ {"ispeed", ispeed},
++ {"ospeed", ospeed},
++ {0, 0}
++};
++
++#define B(baud) {#baud, B##baud}
++static const struct speed speeds[] = {
++ B(0), B(50), B(75), B(110), B(134), B(150), B(200), B(300),
++ B(600), B(1200), B(1800), B(2400), B(4800), B(9600), B(19200), B(38400),
++ B(57600), B(115200), B(230400), B(460800), B(500000), B(576000), B(921600), B(1000000),
++ B(1152000), B(1500000), B(2000000), B(2500000), B(3000000), B(3500000), B(4000000),
++ {"134.5", B134},
++ {"exta", B19200},
++ {"extb", B38400},
++ {0, 0}
++};
++#undef B
++
++static void
++sane(int unset, struct termios *m)
++{
++ const struct key *op = keys;
++ for (; op->op; op++)
++ m->c_cc[op->index] = op->sanevalue;
++ m->c_cc[VMIN] = 1;
++ m->c_cc[VTIME] = 0;
++ (void) unset;
++}
++
++static int
++isxnumber(char* str)
++{
++ if (!*str)
++ return 0;
++ for (; *str; str++)
++ if (!isxdigit(*str))
++ return 0;
++ return 1;
++}
++
++static void
++decodehex(char *dest, char* src)
++{
++ while (*src) {
++ char hi = *src++;
++ char lo = *src++;
++ hi = (hi & 15) + 9 * !isdigit(hi);
++ lo = (lo & 15) + 9 * !isdigit(lo);
++ *dest++ = (hi << 4) | lo;
++ }
++}
++
++static void
++setwinsize(long y, long x)
++{
++ struct winsize winsize;
++ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize))
++ eprintf("TIOCGWINSZ <stdin>:");
++ if (y >= 0)
++ winsize.ws_row = y;
++ if (x >= 0)
++ winsize.ws_col = x;
++ if (ioctl(STDIN_FILENO, TIOCSWINSZ, &winsize))
++ eprintf("TIOCSWINSZ <stdin>:");
++}
++
++static void
++setoperand_mode(int unset, const struct mode *op, struct termios *mode)
++{
++ tcflag_t *bitsp = 0;
++
++ switch (op->type) {
++ case CTRL: bitsp = &mode->c_cflag; break;
++ case IN: bitsp = &mode->c_iflag; break;
++ case OUT: bitsp = &mode->c_oflag; break;
++ case LOCAL: bitsp = &mode->c_lflag; break;
++ case SPEC: break;
++ default: abort();
++ }
++
++ if (bitsp) {
++ *bitsp &= ~op->clear;
++ if (!unset)
++ *bitsp |= op->set;
++ else
++ *bitsp &= ~op->set;
++ }
++
++ if (op->fun)
++ op->fun(unset, mode);
++}
++
++static int
++parseoperand_mode(char *arg, struct termios *mode)
++{
++ const struct mode *op = modes;
++ const struct mode *op_proper;
++ int unset = *arg == '-';
++ int flags_set, flags_unset;
++
++ arg += unset;
++ while (op->op && strcmp(arg, op->op))
++ op++;
++ if (!op->op)
++ return -1;
++ if (unset && !(op->flags & BOOL))
++ return -1;
++
++ switch (op->type) {
++ case CTRL:
++ case IN:
++ case OUT:
++ case LOCAL:
++ case SPEC:
++ setoperand_mode(unset, op, mode);
++ return 0;
++ case COMB:
++ break;
++ default:
++ abort();
++ }
++
++ flags_set = (int)(op->set);
++ flags_unset = (int)(op->clear);
++ op_proper = op;
++
++ if (flags_unset || flags_set) {
++ for (op = modes; op->op; op++) {
++ if (op->type == COMB)
++ continue;
++ if (flags_unset && (op->flags & flags_unset))
++ setoperand_mode(!unset, op, mode);
++ if (flags_set && (op->flags & flags_set))
++ setoperand_mode(unset, op, mode);
++ }
++ }
++
++ if (op_proper->fun)
++ op_proper->fun(unset, mode);
++
++ return 0;
++}
++
++static long long
++estrtonum_radix(const char *numstr, long long minval, long long maxval, int radix)
++{
++ long long ll = 0;
++ char *ep;
++ errno = 0;
++ ll = strtoll(numstr, &ep, radix);
++ if (numstr == ep || *ep != '\0')
++ eprintf("strtoll %s: invalid\n", numstr);
++ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
++ eprintf("strtoll %s: too small\n", numstr);
++ else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
++ eprintf("strtoll %s: too large\n", numstr);
++ return ll;
++}
++
++static int
++parseoperand_key(char *arg0, char *arg1, struct termios *mode)
++{
++ const struct key *op = keys;
++ cc_t value;
++
++ while (op->op && strcmp(arg0, op->op))
++ op++;
++ if (!op->op)
++ return -1;
++
++ if (!arg1)
++ eprintf("missing argument for operand: %s\n", arg0);
++
++ if (!strcmp(arg1, "^-") || !strcmp(arg1, "undef"))
++ value = _POSIX_VDISABLE;
++ else if (!strcmp(arg1, "^?"))
++ value = 127;
++ else if (!arg1[0] || !arg1[1])
++ value = arg1[0];
++ else if (arg1[0] == '^')
++ value = (cc_t)(arg1[1]) & ~0x60;
++ else if (strstr(arg1, "0x") == arg1)
++ value = estrtonum_radix(arg1 + 2, 0, CC_MAX, 16);
++ else if (arg1[0] == '0' && arg1[1])
++ value = estrtonum_radix(arg1 + 1, 0, CC_MAX, 8);
++ else
++ value = estrtonum_radix(arg1 + 0, 0, CC_MAX, 10);
++
++ mode->c_cc[op->index] = value;
++ return 0;
++}
++
++static int
++parseoperand_int(char *arg0, char *arg1, struct termios *mode)
++{
++ const struct intvalued *op = ints;
++
++ while (op->op && strcmp(arg0, op->op))
++ op++;
++ if (!op->op)
++ return -1;
++
++ if (!arg1)
++ eprintf("missing argument for operand: %s\n", arg0);
++
++ op->fun(arg1, mode);
++ return 0;
++}
++
++static const char *
++baudtostr(speed_t baud)
++{
++ const struct speed *speed = speeds;
++ while (speed->str && speed->speed != baud)
++ speed++;
++ return speed->str ? speed->str : "0";
++}
++
++static int
++parsespeed(char *arg, struct speed *ret)
++{
++ const struct speed *speed = speeds;
++ while (speed->str && strcmp(arg, speed->str))
++ speed++;
++ if (!speed->str)
++ return -1;
++ *ret = *speed;
++ return 0;
++}
++
++static void
++eparsespeed(char *arg, struct speed *ret)
++{
++ if (parsespeed(arg, ret))
++ eprintf("invalid speed parameter: %s\n", arg);
++}
++
++static void
++ispeed(char *arg, struct termios *m)
++{
++ struct speed speed;
++ eparsespeed(arg, &speed);
++ if (cfsetispeed(m, speed.speed))
++ eprintf("cfsetispeed %s:", speed.str);
++}
++
++static void
++ospeed(char *arg, struct termios *m)
++{
++ struct speed speed;
++ eparsespeed(arg, &speed);
++ if (cfsetospeed(m, speed.speed))
++ eprintf("cfsetospeed %s:", speed.str);
++}
++
++static void
++printtoken(const char *fmt, ...)
++{
++ static size_t width = 0;
++ static size_t pos = 0;
++ static char buf[BUFSIZ];
++ va_list ap;
++ int len;
++
++ if (!width) {
++ struct winsize winsize;
++ if (!ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize))
++ if (winsize.ws_col > 40)
++ width = winsize.ws_col;
++ if (!width)
++ width = SIZE_MAX;
++ }
++
++ if (!strcmp(fmt, "\n")) {
++ if (pos)
++ printf("\n");
++ pos = 0;
++ return;
++ }
++
++ va_start(ap, fmt);
++ len = vsnprintf(buf, sizeof(buf), fmt, ap);
++ va_end(ap);
++ if (len < 0 || (size_t)len >= sizeof(buf))
++ eprintf("vsnprintf:");
++
++ if (pos + !!pos + len > width) {
++ printf("\n");
++ pos = 0;
++ } else if (pos) {
++ printf(" ");
++ pos++;
++ }
++
++ printf("%s", buf);
++ pos += len;
++}
++
++static const char*
++keytostr(cc_t key)
++{
++ static char buf[5];
++ int r;
++ if (key == _POSIX_VDISABLE)
++ return "undef";
++ else if (key < (cc_t)' ')
++ r = snprintf(buf, sizeof(buf), "^%c", key + '@');
++ else if (key < 127)
++ r = snprintf(buf, sizeof(buf), "%c", key);
++ else if (key == 127)
++ r = snprintf(buf, sizeof(buf), "^?");
++ else if (key < 128 + ' ')
++ r = snprintf(buf, sizeof(buf), "M-^%c", key - 128 + '@');
++ else if (key == 128 + 127)
++ r = snprintf(buf, sizeof(buf), "M-^?");
++ else
++ r = snprintf(buf, sizeof(buf), "M-%c", key - 128);
++ if (r < 0 || (size_t)r >= sizeof(buf))
++ eprintf("snprintf:");
++ return buf;
++}
++
++static void
++displaysettings(struct termios *m, int all)
++{
++ const struct key *kbd = keys;
++ const struct mode *mod = modes;
++ struct winsize winsize;
++ speed_t in, out;
++ tcflag_t *bitsp, mask;
++
++ in = cfgetispeed(m);
++ out = cfgetospeed(m);
++ if (!in || in == out) {
++ if (all || out != B38400)
++ printtoken("speed %s baud;", baudtostr(out));
++ } else {
++ printtoken("ispeed %s baud;", baudtostr(in));
++ printtoken("ospeed %s baud;", baudtostr(out));
++ }
++
++ if (all) {
++ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize))
++ eprintf("TIOCGWINSZ <stdin>:");
++ printtoken("rows %u;", winsize.ws_row);
++ printtoken("columns %u;", winsize.ws_col);
++ }
++ printtoken("\n");
++
++ if (all || m->c_line != 0)
++ printtoken("line = %u;", (unsigned long)(m->c_line));
++ if (all || (m->c_cc[VMIN] != 1 && !(m->c_lflag & ICANON)))
++ printtoken("min = %u;", (unsigned long)(m->c_cc[VMIN]));
++ if (all || (m->c_cc[VTIME] != 0 && !(m->c_lflag & ICANON)))
++ printtoken("time = %u;", (unsigned long)(m->c_cc[VTIME]));
++ printtoken("\n");
++
++ for (; kbd->op; kbd++)
++ if (all || m->c_cc[kbd->index] != kbd->sanevalue)
++ printtoken("%s = %s;", kbd->op, keytostr(m->c_cc[kbd->index]));
++ printtoken("\n");
++
++ for (; mod->op; mod++) {
++ switch (mod->type) {
++ case CTRL: bitsp = &m->c_cflag; break;
++ case IN: bitsp = &m->c_iflag; break;
++ case OUT: bitsp = &m->c_oflag; break;
++ case LOCAL: bitsp = &m->c_lflag; break;
++ default: bitsp = 0; break;
++ }
++ if (!bitsp || (mod->flags & DUP))
++ continue;
++ mask = mod->clear ? mod->clear : mod->set;
++ if ((*bitsp & mask) == mod->set) {
++ if (all || (mod->flags & INSANE) || !(mod->flags & SANE))
++ printtoken("%s", mod->op);
++ }
++ else if (mod->flags & BOOL) {
++ if (all || (mod->flags & SANE) || !(mod->flags & INSANE))
++ printtoken("-%s", mod->op);
++ }
++ }
++ printtoken("\n");
++}
++
++static void
++usage(void)
++{
++ eprintf("usage: %s [-a | -g] [operand ...]\n", argv0);
++}
++
++int
++main(int argc, char *argv[])
++{
++ struct termios mode;
++ struct termios mode2;
++ struct winsize winsize;
++ struct speed speed;
++ int aflag = 0;
++ int gflag = 0;
++ size_t n;
++ unsigned char *buf;
++ char *p;
++ speed_t in, out;
++
++ for (argv0 = *argv++, argc--; argc; argv++, argc--) {
++ if (!strcmp(*argv, "-ag") || !strcmp(*argv, "-ga")) {
++ aflag = gflag = 1;
++ } else if (!strcmp(*argv, "-g")) {
++ gflag = 1;
++ } else if (!strcmp(*argv, "-a")) {
++ aflag = 1;
++ } else if (!strcmp(*argv, "--")) {
++ argv++, argc--;
++ break;
++ } else {
++ break;
++ }
++ }
++
++ if (aflag && gflag)
++ usage();
++
++ memset(&mode, 0, sizeof(mode));
++ if (tcgetattr(STDIN_FILENO, &mode))
++ eprintf("tcgetattr <stdin>:");
++ memcpy(&mode2, &mode, sizeof(mode));
++
++ for (; *argv; argv++) {
++ if (**argv == '=') {
++ p = *argv + 1;
++ if (strlen(p) != sizeof(mode) * 2 || !isxnumber(p))
++ goto invalid;
++ decodehex((char *)&mode, p);
++ } else if (!parseoperand_mode(*argv, &mode)) {
++ /* do nothing. */
++ } else if (!parseoperand_key(argv[0], argv[1], &mode)) {
++ argv++;
++ } else if (!parseoperand_int(argv[0], argv[1], &mode)) {
++ argv++;
++ } else if (!parsespeed(*argv, &speed)) {
++ if (cfsetispeed(&mode, speed.speed))
++ eprintf("cfsetispeed %s:", speed.str);
++ if (cfsetospeed(&mode, speed.speed))
++ eprintf("cfsetospeed %s:", speed.str);
++ } else {
++ goto invalid;
++ }
++ }
++
++ if (memcmp(&mode, &mode2, sizeof(mode))) {
++ memset(&mode2, 0, sizeof(mode2));
++ if (tcsetattr(STDIN_FILENO, drain_requested ? TCSADRAIN : TCSANOW, &mode))
++ eprintf("tcsetattr <stdin>:");
++ if (tcgetattr(STDIN_FILENO, &mode2))
++ eprintf("tcgetattr <stdin>:");
++ if (memcmp(&mode, &mode2, sizeof(mode)))
++ eprintf("tcsetattr <stdin>: unable to apply all operands\n");
++ }
++
++ if (gflag) {
++ buf = (unsigned char *)&mode;
++ printf("=");
++ for (n = sizeof(mode); n--; buf++)
++ printf("%02x", *buf);
++ printf("\n");
++ }
++
++ if (output_size_requested) {
++ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize))
++ eprintf("TIOCGWINSZ <stdin>:");
++ printf("%u %u\n", winsize.ws_row, winsize.ws_col);
++ }
++
++ if (output_speed_requested) {
++ in = cfgetispeed(&mode);
++ out = cfgetospeed(&mode);
++ if (!in || in == out)
++ printf("%s\n", baudtostr(out));
++ else
++ printf("%s %s\n", baudtostr(in), baudtostr(out));
++ }
++
++ if ((aflag || !argc) && !gflag)
++ displaysettings(&mode, aflag);
++
++ return 0;
++
++invalid:
++ eprintf("invalid operand: %s\n", *argv);
++}
+--
+2.8.1
+
diff --git a/core/ubase/patch/0004-stty-cleaner-output-when-no-arguments-are-used.patch b/core/ubase/patch/0004-stty-cleaner-output-when-no-arguments-are-used.patch
new file mode 100644
index 00000000..ebe8e0a3
--- /dev/null
+++ b/core/ubase/patch/0004-stty-cleaner-output-when-no-arguments-are-used.patch
@@ -0,0 +1,96 @@
+From 9f00ed516b949f735d4e0a4422a0e23e4df72211 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Mattias=20Andr=C3=A9e?= <maandree@kth.se>
+Date: Wed, 30 Mar 2016 16:46:07 +0200
+Subject: [PATCH] stty: cleaner output when no arguments are used
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Mattias Andrée <maandree@kth.se>
+---
+ stty.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/stty.c b/stty.c
+index c65748a..3e90b8f 100644
+--- a/stty.c
++++ b/stty.c
+@@ -1,4 +1,6 @@
+ /* See LICENSE file for copyright and license details. */
++#include <sys/ioctl.h>
++
+ #include <ctype.h>
+ #include <errno.h>
+ #include <limits.h>
+@@ -7,7 +9,6 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <sys/ioctl.h>
+ #include <termios.h>
+ #include <unistd.h>
+
+@@ -113,7 +114,8 @@ enum {
+ CRT = 1024,
+ DEC = 2048,
+ NL = 4096,
+- COOKED = 8192
++ COOKED = 8192,
++ DEF = 16384
+ };
+
+ struct mode {
+@@ -149,10 +151,10 @@ static const struct mode modes[] = {
+ {"cs5", CTRL, CS5, CSIZE, 0, 0},
+ {"cs6", CTRL, CS6, CSIZE, 0, 0},
+ {"cs7", CTRL, CS7, CSIZE, 0, 0},
+- {"cs8", CTRL, CS8, CSIZE, 0, 0},
++ {"cs8", CTRL, CS8, CSIZE, 0, DEF},
+ {"cstopb", CTRL, CSTOPB, 0, 0, BOOL},
+ {"hup", CTRL, HUPCL, 0, 0, BOOL | DUP},
+- {"hupcl", CTRL, HUPCL, 0, 0, BOOL},
++ {"hupcl", CTRL, HUPCL, 0, 0, BOOL | DEF},
+ {"parenb", CTRL, PARENB, 0, 0, BOOL | PASS8 | LITOUT},
+ {"parodd", CTRL, PARODD, 0, 0, BOOL},
+
+@@ -169,7 +171,7 @@ static const struct mode modes[] = {
+ {"iutf8", IN, IUTF8, 0, 0, BOOL | SANE},
+ {"ixany", IN, IXANY, 0, 0, BOOL | INSANE | DECCTLQ},
+ {"ixoff", IN, IXOFF, 0, 0, BOOL | INSANE},
+- {"ixon", IN, IXON, 0, 0, BOOL},
++ {"ixon", IN, IXON, 0, 0, BOOL | DEF},
+ {"parmrk", IN, PARMRK, 0, 0, BOOL},
+ {"tandem", IN, IXOFF, 0, 0, BOOL | DUP},
+
+@@ -591,6 +593,14 @@ keytostr(cc_t key)
+ return buf;
+ }
+
++static int
++isdefault(int flags)
++{
++ if (flags & (SANE | INSANE))
++ return (flags & SANE) || !(flags & INSANE);
++ return flags & DEF;
++}
++
+ static void
+ displaysettings(struct termios *m, int all)
+ {
+@@ -643,11 +653,11 @@ displaysettings(struct termios *m, int all)
+ continue;
+ mask = mod->clear ? mod->clear : mod->set;
+ if ((*bitsp & mask) == mod->set) {
+- if (all || (mod->flags & INSANE) || !(mod->flags & SANE))
++ if (all || !isdefault(mod->flags))
+ printtoken("%s", mod->op);
+ }
+ else if (mod->flags & BOOL) {
+- if (all || (mod->flags & SANE) || !(mod->flags & INSANE))
++ if (all || isdefault(mod->flags))
+ printtoken("-%s", mod->op);
+ }
+ }
+--
+2.8.1
+
diff --git a/core/ubase/patch/0005-stty-fix-casting-bug.patch b/core/ubase/patch/0005-stty-fix-casting-bug.patch
new file mode 100644
index 00000000..26faab07
--- /dev/null
+++ b/core/ubase/patch/0005-stty-fix-casting-bug.patch
@@ -0,0 +1,35 @@
+From 70b734d269da4a0c92381f4e892e3c42f959e298 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Mattias=20Andr=C3=A9e?= <maandree@kth.se>
+Date: Wed, 30 Mar 2016 16:46:08 +0200
+Subject: [PATCH] stty: fix casting bug
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Mattias Andrée <maandree@kth.se>
+---
+ stty.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/stty.c b/stty.c
+index 3e90b8f..9f4307b 100644
+--- a/stty.c
++++ b/stty.c
+@@ -629,11 +629,11 @@ displaysettings(struct termios *m, int all)
+ printtoken("\n");
+
+ if (all || m->c_line != 0)
+- printtoken("line = %u;", (unsigned long)(m->c_line));
++ printtoken("line = %u;", (unsigned)(m->c_line));
+ if (all || (m->c_cc[VMIN] != 1 && !(m->c_lflag & ICANON)))
+- printtoken("min = %u;", (unsigned long)(m->c_cc[VMIN]));
++ printtoken("min = %u;", (unsigned)(m->c_cc[VMIN]));
+ if (all || (m->c_cc[VTIME] != 0 && !(m->c_lflag & ICANON)))
+- printtoken("time = %u;", (unsigned long)(m->c_cc[VTIME]));
++ printtoken("time = %u;", (unsigned)(m->c_cc[VTIME]));
+ printtoken("\n");
+
+ for (; kbd->op; kbd++)
+--
+2.8.1
+
diff --git a/core/ubase/patch/0006-stty-add-symbolic-values-for-line-disciplines.patch b/core/ubase/patch/0006-stty-add-symbolic-values-for-line-disciplines.patch
new file mode 100644
index 00000000..822ddf1d
--- /dev/null
+++ b/core/ubase/patch/0006-stty-add-symbolic-values-for-line-disciplines.patch
@@ -0,0 +1,139 @@
+From d2bc7a470249707740e001b5c996aa906181553f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Mattias=20Andr=C3=A9e?= <maandree@kth.se>
+Date: Wed, 30 Mar 2016 16:46:09 +0200
+Subject: [PATCH] stty: add symbolic values for line disciplines
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Mattias Andrée <maandree@kth.se>
+---
+ stty.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 59 insertions(+), 4 deletions(-)
+
+diff --git a/stty.c b/stty.c
+index 9f4307b..e21ab24 100644
+--- a/stty.c
++++ b/stty.c
+@@ -95,7 +95,6 @@ static void size(int unset, struct termios *m) { output_size_requested = 1; (v
+ static void speed(int unset, struct termios *m) { output_speed_requested = 1; (void) m; (void) unset; }
+ static void tabs(int unset, struct termios *m) { m->c_oflag &= ~TABDLY, m->c_oflag |= unset ? TAB3 : TAB0; }
+ static void cols(char *arg, struct termios *m) { setwinsize(-1, estrtonum(arg, 0, USHRT_MAX)); (void) m; }
+-static void line(char *arg, struct termios *m) { m->c_line = estrtonum(arg, 0, 255); }
+ static void min(char *arg, struct termios *m) { m->c_cc[VMIN] = estrtonum(arg, 0, CC_MAX); }
+ static void rows(char *arg, struct termios *m) { setwinsize(estrtonum(arg, 0, USHRT_MAX), -1); (void) m; }
+ static void stime(char *arg, struct termios *m) { m->c_cc[VTIME] = estrtonum(arg, 0, CC_MAX); }
+@@ -143,6 +142,11 @@ struct speed {
+ speed_t speed;
+ };
+
++struct line {
++ const char *str;
++ unsigned char value;
++};
++
+ static const struct mode modes[] = {
+ {"clocal", CTRL, CLOCAL, 0, 0, BOOL},
+ {"cmspar", CTRL, CMSPAR, 0, 0, BOOL},
+@@ -267,7 +271,6 @@ static const struct key keys[] = {
+ static const struct intvalued ints[] = {
+ {"cols", cols},
+ {"columns", cols},
+- {"line", line},
+ {"min", min},
+ {"rows", rows},
+ {"time", stime},
+@@ -289,6 +292,26 @@ static const struct speed speeds[] = {
+ };
+ #undef B
+
++static const struct line lines[] = {
++ {"tty", N_TTY},
++ {"slip", N_SLIP},
++ {"mouse", N_MOUSE},
++ {"ppp", N_PPP},
++ {"strip", N_STRIP},
++ {"ax25", N_AX25},
++ {"x25", N_X25},
++ {"6pack", N_6PACK},
++ {"masc", N_MASC},
++ {"r3964", N_R3964},
++ {"profibus", N_PROFIBUS_FDL},
++ {"irda", N_IRDA},
++ {"smsblock", N_SMSBLOCK},
++ {"hdlc", N_HDLC},
++ {"syncppp", N_SYNC_PPP},
++ {"hci", N_HCI},
++ {0, 0}
++};
++
+ static void
+ sane(int unset, struct termios *m)
+ {
+@@ -489,6 +512,27 @@ baudtostr(speed_t baud)
+ return speed->str ? speed->str : "0";
+ }
+
++static const char*
++linetostr(unsigned value)
++{
++ const struct line *ln = lines;
++ while (ln->str && ln->value != value)
++ ln++;
++ return ln->str;
++}
++
++static void
++line(char *arg, struct termios *m)
++{
++ const struct line *ln = lines;
++ while (ln->str && strcmp(ln->str, arg))
++ ln++;
++ if (ln->str)
++ m->c_line = ln->value;
++ else
++ m->c_line = estrtonum(arg, 0, 255);
++}
++
+ static int
+ parsespeed(char *arg, struct speed *ret)
+ {
+@@ -609,6 +653,7 @@ displaysettings(struct termios *m, int all)
+ struct winsize winsize;
+ speed_t in, out;
+ tcflag_t *bitsp, mask;
++ const char *linestr;
+
+ in = cfgetispeed(m);
+ out = cfgetospeed(m);
+@@ -628,8 +673,13 @@ displaysettings(struct termios *m, int all)
+ }
+ printtoken("\n");
+
+- if (all || m->c_line != 0)
+- printtoken("line = %u;", (unsigned)(m->c_line));
++ if (all || m->c_line != 0) {
++ linestr = linetostr(m->c_line);
++ if (linestr)
++ printtoken("line = %s;", linestr);
++ else
++ printtoken("line = %u;", (unsigned)(m->c_line));
++ }
+ if (all || (m->c_cc[VMIN] != 1 && !(m->c_lflag & ICANON)))
+ printtoken("min = %u;", (unsigned)(m->c_cc[VMIN]));
+ if (all || (m->c_cc[VTIME] != 0 && !(m->c_lflag & ICANON)))
+@@ -719,6 +769,11 @@ main(int argc, char *argv[])
+ argv++;
+ } else if (!parseoperand_int(argv[0], argv[1], &mode)) {
+ argv++;
++ } else if (!strcmp(argv[0], "line")) {
++ if (!argv[1])
++ eprintf("missing argument for operand: %s\n", argv[0]);
++ line(argv[1], &mode);
++ argv++;
+ } else if (!parsespeed(*argv, &speed)) {
+ if (cfsetispeed(&mode, speed.speed))
+ eprintf("cfsetispeed %s:", speed.str);
+--
+2.8.1
+
diff --git a/core/ubase/patch/0007-stty-simplify.patch b/core/ubase/patch/0007-stty-simplify.patch
new file mode 100644
index 00000000..e4039231
--- /dev/null
+++ b/core/ubase/patch/0007-stty-simplify.patch
@@ -0,0 +1,49 @@
+From 450963b1b1167b6b38dd0d78612015d79a9381bf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Mattias=20Andr=C3=A9e?= <maandree@kth.se>
+Date: Sat, 2 Apr 2016 02:39:15 +0200
+Subject: [PATCH] stty: simplify
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Mattias Andrée <maandree@kth.se>
+---
+ stty.c | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+diff --git a/stty.c b/stty.c
+index e21ab24..9da517c 100644
+--- a/stty.c
++++ b/stty.c
+@@ -438,12 +438,12 @@ parseoperand_mode(char *arg, struct termios *mode)
+ }
+
+ static long long
+-estrtonum_radix(const char *numstr, long long minval, long long maxval, int radix)
++estrtonum_anyradix(const char *numstr, long long minval, long long maxval)
+ {
+ long long ll = 0;
+ char *ep;
+ errno = 0;
+- ll = strtoll(numstr, &ep, radix);
++ ll = strtoll(numstr, &ep, 0);
+ if (numstr == ep || *ep != '\0')
+ eprintf("strtoll %s: invalid\n", numstr);
+ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+@@ -475,12 +475,8 @@ parseoperand_key(char *arg0, char *arg1, struct termios *mode)
+ value = arg1[0];
+ else if (arg1[0] == '^')
+ value = (cc_t)(arg1[1]) & ~0x60;
+- else if (strstr(arg1, "0x") == arg1)
+- value = estrtonum_radix(arg1 + 2, 0, CC_MAX, 16);
+- else if (arg1[0] == '0' && arg1[1])
+- value = estrtonum_radix(arg1 + 1, 0, CC_MAX, 8);
+ else
+- value = estrtonum_radix(arg1 + 0, 0, CC_MAX, 10);
++ value = estrtonum_anyradix(arg1, 0, CC_MAX);
+
+ mode->c_cc[op->index] = value;
+ return 0;
+--
+2.8.1
+
diff --git a/core/ubase/patch/0008-stty-Fix-indentation.patch b/core/ubase/patch/0008-stty-Fix-indentation.patch
new file mode 100644
index 00000000..f2e5847f
--- /dev/null
+++ b/core/ubase/patch/0008-stty-Fix-indentation.patch
@@ -0,0 +1,79 @@
+From bfa40d29da6608660ed453ccc2b679831eeb0e1b Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 14 Jun 2016 22:04:15 -0700
+Subject: [PATCH] stty: Fix indentation
+
+---
+ stty.c | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/stty.c b/stty.c
+index 9da517c..9aa52b5 100644
+--- a/stty.c
++++ b/stty.c
+@@ -21,7 +21,7 @@
+ * convenience and compatibility with other implementations.
+ */
+
+-#define CC_MAX 255
++#define CC_MAX 255
+
+ static int output_size_requested = 0;
+ static int output_speed_requested = 0;
+@@ -282,9 +282,9 @@ static const struct intvalued ints[] = {
+ #define B(baud) {#baud, B##baud}
+ static const struct speed speeds[] = {
+ B(0), B(50), B(75), B(110), B(134), B(150), B(200), B(300),
+- B(600), B(1200), B(1800), B(2400), B(4800), B(9600), B(19200), B(38400),
+- B(57600), B(115200), B(230400), B(460800), B(500000), B(576000), B(921600), B(1000000),
+- B(1152000), B(1500000), B(2000000), B(2500000), B(3000000), B(3500000), B(4000000),
++ B(600), B(1200), B(1800), B(2400), B(4800), B(9600), B(19200), B(38400),
++ B(57600), B(115200), B(230400), B(460800), B(500000), B(576000), B(921600), B(1000000),
++ B(1152000), B(1500000), B(2000000), B(2500000), B(3000000), B(3500000), B(4000000),
+ {"134.5", B134},
+ {"exta", B19200},
+ {"extb", B38400},
+@@ -403,16 +403,16 @@ parseoperand_mode(char *arg, struct termios *mode)
+ return -1;
+
+ switch (op->type) {
+- case CTRL:
+- case IN:
+- case OUT:
+- case LOCAL:
+- case SPEC:
++ case CTRL:
++ case IN:
++ case OUT:
++ case LOCAL:
++ case SPEC:
+ setoperand_mode(unset, op, mode);
+ return 0;
+- case COMB:
++ case COMB:
+ break;
+- default:
++ default:
+ abort();
+ }
+
+@@ -689,11 +689,11 @@ displaysettings(struct termios *m, int all)
+
+ for (; mod->op; mod++) {
+ switch (mod->type) {
+- case CTRL: bitsp = &m->c_cflag; break;
+- case IN: bitsp = &m->c_iflag; break;
+- case OUT: bitsp = &m->c_oflag; break;
+- case LOCAL: bitsp = &m->c_lflag; break;
+- default: bitsp = 0; break;
++ case CTRL: bitsp = &m->c_cflag; break;
++ case IN: bitsp = &m->c_iflag; break;
++ case OUT: bitsp = &m->c_oflag; break;
++ case LOCAL: bitsp = &m->c_lflag; break;
++ default: bitsp = 0; break;
+ }
+ if (!bitsp || (mod->flags & DUP))
+ continue;
+--
+2.8.1
+
diff --git a/core/ubase/patch/0009-stty-Fix-build-with-musl-libc.patch b/core/ubase/patch/0009-stty-Fix-build-with-musl-libc.patch
new file mode 100644
index 00000000..ae1373f5
--- /dev/null
+++ b/core/ubase/patch/0009-stty-Fix-build-with-musl-libc.patch
@@ -0,0 +1,53 @@
+From 7bf3cab74f99163de9aced05a424e359fbeecb82 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 14 Jun 2016 22:19:18 -0700
+Subject: [PATCH] stty: Fix build with musl libc
+
+---
+ stty.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/stty.c b/stty.c
+index 9aa52b5..3fc5844 100644
+--- a/stty.c
++++ b/stty.c
+@@ -1,5 +1,6 @@
+ /* See LICENSE file for copyright and license details. */
+ #include <sys/ioctl.h>
++#include <sys/ttydefaults.h>
+
+ #include <ctype.h>
+ #include <errno.h>
+@@ -37,7 +38,9 @@ raw(int unset, struct termios *m)
+ {
+ if (!unset) {
+ m->c_iflag = 0;
++#ifdef XCASE
+ m->c_lflag &= ~XCASE;
++#endif
+ m->c_cc[VMIN] = 1;
+ m->c_cc[VTIME] = 0;
+ } else {
+@@ -149,7 +152,9 @@ struct line {
+
+ static const struct mode modes[] = {
+ {"clocal", CTRL, CLOCAL, 0, 0, BOOL},
++#ifdef CMSPAR
+ {"cmspar", CTRL, CMSPAR, 0, 0, BOOL},
++#endif
+ {"cread", CTRL, CREAD, 0, 0, BOOL | SANE},
+ {"crtscts", CTRL, CRTSCTS, 0, 0, BOOL},
+ {"cs5", CTRL, CS5, CSIZE, 0, 0},
+@@ -222,7 +227,9 @@ static const struct mode modes[] = {
+ {"noflsh", LOCAL, NOFLSH, 0, 0, BOOL | INSANE},
+ {"prterase", LOCAL, ECHOPRT, 0, 0, BOOL | DUP},
+ {"tostop", LOCAL, TOSTOP, 0, 0, BOOL | INSANE},
++#ifdef XCASE
+ {"xcase", LOCAL, XCASE, 0, 0, BOOL | INSANE | LCASE},
++#endif
+
+ {"cbreak", COMB, 0, CBREAK, 0, BOOL | DUP},
+ {"cooked", COMB, COOKED, 0, cooked, BOOL | DUP},
+--
+2.8.1
+