From bdc143a7aa3f51a46eceec62b0b364599533fa21 Mon Sep 17 00:00:00 2001 From: Lunaixsky Date: Sun, 28 Jul 2024 22:50:17 +0100 Subject: [PATCH 1/1] Change of vterm handling logic on backend chardev input event (#40) * fix: term should not ignore underlying input event * term should always respond the input event from underlying termport awared character device, by process the raw input buffer according one's lflags.ICANNO setting when the data is avaliable * fix: race when parent get destroyed before children * fix: orphan a process's children when it is about to destroy * fix: devzero: mis-used offset cause segfault * add support of setting serial io speed * fix: truncate the overflowed input instead of running over. * rewrite the line control * rewrite the line control implementation to make it clean and less hacky. * correct some POSIX compliance issue related to some control characters. * fix issue where ANSI line control failed to echo the transformed special character * add a sanity filter to sh to filter out any unprintable character. * fix: make lxconsole work with vterm refactor * fix: tdev_do_read do not check the linebuffer::sflag * add a config term for lxconsole (vgacon) * rename tty/tty.c to vga_rawtty.c for clarity --- lunaix-os/hal/char/LBuild | 6 +- lunaix-os/hal/char/LConfig | 7 + lunaix-os/hal/char/devzero.c | 4 +- lunaix-os/hal/char/lxconsole.c | 28 +- lunaix-os/hal/char/serial.c | 30 +- lunaix-os/hal/char/uart/16x50.h | 5 +- lunaix-os/hal/char/uart/16x50_base.c | 27 +- lunaix-os/hal/gfxa/vga/LBuild | 3 +- .../tty/tty.c => hal/gfxa/vga/vga_rawtty.c} | 14 +- lunaix-os/hal/term/LBuild | 1 + lunaix-os/hal/term/default_ops.c | 25 ++ lunaix-os/hal/term/lcntls/ansi_cntl.c | 21 +- lunaix-os/hal/term/lcntls/lcntl.c | 257 +++++++++++------- lunaix-os/hal/term/lcntls/lcntl.h | 77 ++++++ lunaix-os/hal/term/term.c | 61 +++-- lunaix-os/hal/term/term_io.c | 112 ++++---- lunaix-os/includes/hal/serial.h | 2 + lunaix-os/includes/hal/term.h | 58 ++-- lunaix-os/includes/lunaix/ds/rbuffer.h | 26 +- lunaix-os/includes/usr/lunaix/serial.h | 13 +- lunaix-os/kernel/LBuild | 1 - lunaix-os/kernel/ds/rbuffer.c | 6 +- lunaix-os/kernel/kinit.c | 5 - lunaix-os/kernel/process/sched.c | 21 +- lunaix-os/kernel/process/signal.c | 11 +- lunaix-os/usr/init/init.c | 3 + lunaix-os/usr/libc/includes/termios.h | 9 +- lunaix-os/usr/sh/sh.c | 22 ++ 28 files changed, 600 insertions(+), 255 deletions(-) rename lunaix-os/{kernel/tty/tty.c => hal/gfxa/vga/vga_rawtty.c} (87%) create mode 100644 lunaix-os/hal/term/default_ops.c create mode 100644 lunaix-os/hal/term/lcntls/lcntl.h diff --git a/lunaix-os/hal/char/LBuild b/lunaix-os/hal/char/LBuild index 88b3310..c00a394 100644 --- a/lunaix-os/hal/char/LBuild +++ b/lunaix-os/hal/char/LBuild @@ -4,5 +4,7 @@ sources([ "devnull.c", "serial.c", "devzero.c", - "lxconsole.c", -]) \ No newline at end of file +]) + +if config("vga_console"): + sources("lxconsole.c") \ No newline at end of file diff --git a/lunaix-os/hal/char/LConfig b/lunaix-os/hal/char/LConfig index 1b5ead4..157e2d7 100644 --- a/lunaix-os/hal/char/LConfig +++ b/lunaix-os/hal/char/LConfig @@ -5,3 +5,10 @@ def char_device(): """ Controlling support of character devices """ add_to_collection(hal) + + @Term + def vga_console(): + """ Enable VGA console device (text mode only) """ + + type(bool) + default(True) diff --git a/lunaix-os/hal/char/devzero.c b/lunaix-os/hal/char/devzero.c index 9013a47..c637a34 100644 --- a/lunaix-os/hal/char/devzero.c +++ b/lunaix-os/hal/char/devzero.c @@ -6,14 +6,14 @@ static int __zero_rd_pg(struct device* dev, void* buf, size_t offset) { - memset(&((u8_t*)buf)[offset], 0, PAGE_SIZE); + memset(buf, 0, PAGE_SIZE); return PAGE_SIZE; } static int __zero_rd(struct device* dev, void* buf, size_t offset, size_t len) { - memset(&((u8_t*)buf)[offset], 0, len); + memset(buf, 0, len); return len; } diff --git a/lunaix-os/hal/char/lxconsole.c b/lunaix-os/hal/char/lxconsole.c index 6387670..4922297 100644 --- a/lunaix-os/hal/char/lxconsole.c +++ b/lunaix-os/hal/char/lxconsole.c @@ -27,6 +27,7 @@ struct console { + struct capability_meta* tp_cap; struct lx_timer* flush_timer; struct fifo_buf output; struct fifo_buf input; @@ -90,8 +91,12 @@ __lxconsole_listener(struct input_device* dev) } fifo_putone(&lx_console.input, ttychr); - pwake_all(&lx_reader); + struct termport_capability* tpcap; + tpcap = get_capability(lx_console.tp_cap, typeof(*tpcap)); + term_notify_data_avaliable(tpcap); + + pwake_all(&lx_reader); done: return INPUT_EVT_NEXT; } @@ -132,6 +137,14 @@ __tty_read(struct device* dev, void* buf, size_t offset, size_t len) return count + fifo_read(&console->input, buf + count, len - count); } +int +__tty_read_async(struct device* dev, void* buf, size_t offset, size_t len) +{ + struct console* console = (struct console*)dev->underlay; + + return fifo_read(&console->input, buf, len); +} + size_t __find_next_line(size_t start) { @@ -279,13 +292,23 @@ lxconsole_spawn_ttydev(struct device_def* devdef) tty_dev->ops.write_page = __tty_write_pg; tty_dev->ops.read = __tty_read; tty_dev->ops.read_page = __tty_read_pg; + tty_dev->ops.write_async = __tty_write; + tty_dev->ops.read_async = __tty_read_async; waitq_init(&lx_reader); input_add_listener(__lxconsole_listener); + struct termport_capability* tp_cap; + + tp_cap = new_capability(TERMPORT_CAP, struct termport_capability); + term_cap_set_operations(tp_cap, termport_default_ops); + + lx_console.tp_cap = cap_meta(tp_cap); + device_grant_capability(tty_dev, lx_console.tp_cap); + register_device(tty_dev, &devdef->class, "vcon"); - term_create(tty_dev, "FB"); + term_create(tty_dev, "VCON"); return 0; } @@ -295,5 +318,4 @@ static struct device_def lxconsole_def = { .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_BUILTIN), .init = lxconsole_spawn_ttydev }; -// FIXME EXPORT_DEVICE(lxconsole, &lxconsole_def, load_onboot); \ No newline at end of file diff --git a/lunaix-os/hal/char/serial.c b/lunaix-os/hal/char/serial.c index 15a9c9e..803fdb5 100644 --- a/lunaix-os/hal/char/serial.c +++ b/lunaix-os/hal/char/serial.c @@ -46,6 +46,10 @@ serial_end_recv(struct serial_dev* sdev) mark_device_done_read(sdev->dev); pwake_one(&sdev->wq_rxdone); + + struct termport_capability* tpcap; + tpcap = get_capability(sdev->tp_cap, typeof(*tpcap)); + term_notify_data_avaliable(tpcap); } void @@ -223,7 +227,18 @@ __serial_set_speed(struct device* dev, speed_t speed) struct serial_dev* sdev = serial_device(dev); lock_sdev(sdev); - sdev_execmd(sdev, SERIO_SETBRDIV, speed); + sdev_execmd(sdev, SERIO_SETBRDRATE, speed); + + unlock_sdev(sdev); +} + +static void +__serial_set_baseclk(struct device* dev, unsigned int base) +{ + struct serial_dev* sdev = serial_device(dev); + lock_sdev(sdev); + + sdev_execmd(sdev, SERIO_SETBRDBASE, base); unlock_sdev(sdev); } @@ -241,10 +256,16 @@ __serial_set_cntrl_mode(struct device* dev, tcflag_t cflag) #define RXBUF_SIZE 512 +static struct termport_cap_ops tpcap_ops = { + .set_cntrl_mode = __serial_set_cntrl_mode, + .set_clkbase = __serial_set_baseclk, + .set_speed = __serial_set_speed +}; + struct serial_dev* serial_create(struct devclass* class, char* if_ident) { - struct serial_dev* sdev = valloc(sizeof(struct serial_dev)); + struct serial_dev* sdev = vzalloc(sizeof(struct serial_dev)); struct device* dev = device_allocseq(dev_meta(serial_cat), sdev); dev->ops.read = __serial_read; dev->ops.read_page = __serial_read_page; @@ -260,8 +281,9 @@ serial_create(struct devclass* class, char* if_ident) struct termport_capability* tp_cap = new_capability(TERMPORT_CAP, struct termport_capability); - tp_cap->set_speed = __serial_set_speed; - tp_cap->set_cntrl_mode = __serial_set_cntrl_mode; + + term_cap_set_operations(tp_cap, &tpcap_ops); + sdev->tp_cap = cap_meta(tp_cap); waitq_init(&sdev->wq_rxdone); waitq_init(&sdev->wq_txdone); diff --git a/lunaix-os/hal/char/uart/16x50.h b/lunaix-os/hal/char/uart/16x50.h index addedfa..40ebe94 100644 --- a/lunaix-os/hal/char/uart/16x50.h +++ b/lunaix-os/hal/char/uart/16x50.h @@ -69,6 +69,7 @@ struct uart16550 struct llist_header local_ports; struct serial_dev* sdev; ptr_t base_addr; + unsigned int base_clk; int iv; struct @@ -118,12 +119,12 @@ void uart_free(struct uart16550*); static inline int -uart_baud_divisor(struct uart16550* uart, int div) +uart_baud_divisor(struct uart16550* uart, unsigned int div) { u32_t rlc = uart->read_reg(uart, UART_rLC); uart->write_reg(uart, UART_rLC, UART_rLC_DLAB | rlc); - u8_t ls = (div & 0xff), ms = (div & 0xff00) >> 8; + u8_t ls = (div & 0x00ff), ms = (div & 0xff00) >> 8; uart->write_reg(uart, UART_rLS, ls); uart->write_reg(uart, UART_rMS, ms); diff --git a/lunaix-os/hal/char/uart/16x50_base.c b/lunaix-os/hal/char/uart/16x50_base.c index 6e94b84..8b3930f 100644 --- a/lunaix-os/hal/char/uart/16x50_base.c +++ b/lunaix-os/hal/char/uart/16x50_base.c @@ -16,6 +16,7 @@ uart_alloc(ptr_t base_addr) uart->cntl_save.rie = 0; uart->base_addr = base_addr; + uart->base_clk = 115200U; return uart; } @@ -69,9 +70,29 @@ uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args) case SERIO_RXDA: uart_clrie(uart); break; - case SERIO_SETBRDIV: - // TODO - break; + case SERIO_SETBRDRATE: + { + unsigned int div, rate; + + rate = va_arg(args, speed_t); + if (!rate) { + return EINVAL; + } + + div = uart->base_clk / va_arg(args, speed_t); + uart_baud_divisor(uart, div); + break; + } + case SERIO_SETBRDBASE: + { + int clk = va_arg(args, unsigned int); + if (!clk) { + return EINVAL; + } + + uart->base_clk = clk; + break; + } case SERIO_SETCNTRLMODE: uart_set_control_mode(uart, va_arg(args, tcflag_t)); break; diff --git a/lunaix-os/hal/gfxa/vga/LBuild b/lunaix-os/hal/gfxa/vga/LBuild index b05da8c..dc8991a 100644 --- a/lunaix-os/hal/gfxa/vga/LBuild +++ b/lunaix-os/hal/gfxa/vga/LBuild @@ -3,5 +3,6 @@ sources([ "vga_gfxm_ops.c", "vga.c", "vga_mmio_ops.c", - "vga_pci.c" + "vga_pci.c", + "vga_rawtty.c", ]) \ No newline at end of file diff --git a/lunaix-os/kernel/tty/tty.c b/lunaix-os/hal/gfxa/vga/vga_rawtty.c similarity index 87% rename from lunaix-os/kernel/tty/tty.c rename to lunaix-os/hal/gfxa/vga/vga_rawtty.c index e5a913f..21fcd82 100644 --- a/lunaix-os/kernel/tty/tty.c +++ b/lunaix-os/hal/gfxa/vga/vga_rawtty.c @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include #include @@ -113,4 +116,13 @@ tty_put_str_at(char* str, int x, int y) } str++; } -} \ No newline at end of file +} + +static void +vga_rawtty_init() +{ + // FIXME we should get rid of it at some point + tty_init((void*)ioremap(0xB8000, PAGE_SIZE)); + tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK); +} +owloysius_fetch_init(vga_rawtty_init, on_earlyboot); \ No newline at end of file diff --git a/lunaix-os/hal/term/LBuild b/lunaix-os/hal/term/LBuild index 9325917..ea5b2c3 100644 --- a/lunaix-os/hal/term/LBuild +++ b/lunaix-os/hal/term/LBuild @@ -2,6 +2,7 @@ sources([ "term.c", "console.c", "term_io.c", + "default_ops.c", "lcntls/ansi_cntl.c", "lcntls/lcntl.c", ]) \ No newline at end of file diff --git a/lunaix-os/hal/term/default_ops.c b/lunaix-os/hal/term/default_ops.c new file mode 100644 index 0000000..fea8355 --- /dev/null +++ b/lunaix-os/hal/term/default_ops.c @@ -0,0 +1,25 @@ +#include + +static void +__tpcap_default_set_speed(struct device* dev, speed_t speed) +{ + +} + +static void +__tpcap_default_set_baseclk(struct device* dev, unsigned int base) +{ + +} + +static void +__tpcap_default_set_cntrl_mode(struct device* dev, tcflag_t cflag) +{ + +} + +struct termport_cap_ops default_termport_cap_ops = { + .set_cntrl_mode = __tpcap_default_set_cntrl_mode, + .set_clkbase = __tpcap_default_set_baseclk, + .set_speed = __tpcap_default_set_speed +}; \ No newline at end of file diff --git a/lunaix-os/hal/term/lcntls/ansi_cntl.c b/lunaix-os/hal/term/lcntls/ansi_cntl.c index 778eb4b..bc66139 100644 --- a/lunaix-os/hal/term/lcntls/ansi_cntl.c +++ b/lunaix-os/hal/term/lcntls/ansi_cntl.c @@ -9,25 +9,18 @@ * @copyright Copyright (c) 2023 * */ -#include +#include "lcntl.h" #include #define CTRL_MNEMO(chr) (chr - 'A' + 1) -static inline int -__ansi_actcontrol(struct term* termdev, struct linebuffer* lbuf, char chr) +int +__ansi_actcontrol(struct lcntl_state* state, char chr) { - struct rbuffer* cooked = lbuf->next; - switch (chr) { - default: - if ((int)chr < 32) { - rbuffer_put(cooked, '^'); - return rbuffer_put(cooked, chr += 64); - } - break; + if (chr < 32 && chr != '\n') { + lcntl_put_char(state, '^'); + return lcntl_put_char(state, chr += 64); } - return rbuffer_put_nof(cooked, chr); + return lcntl_put_char(state, chr); } - -struct term_lcntl ansi_line_controller = {.process_and_put = __ansi_actcontrol}; \ No newline at end of file diff --git a/lunaix-os/hal/term/lcntls/lcntl.c b/lunaix-os/hal/term/lcntls/lcntl.c index db146e1..fb855cc 100644 --- a/lunaix-os/hal/term/lcntls/lcntl.c +++ b/lunaix-os/hal/term/lcntls/lcntl.c @@ -11,30 +11,85 @@ #include #include +#include "lcntl.h" + #include #include static inline void -raise_sig(struct term* at_term, struct linebuffer* lbuf, int sig) +init_lcntl_state(struct lcntl_state* state, + struct term* tdev, enum lcntl_dir direction) { - term_sendsig(at_term, sig); - lbuf->sflags |= LSTATE_SIGRAISE; + *state = (struct lcntl_state) { + .tdev = tdev, + ._lf = tdev->lflags, + ._cf = tdev->cflags, + .direction = direction, + .echobuf = tdev->line_out.current, + }; + + struct linebuffer* lb; + if (direction == INBOUND) { + state->_if = tdev->iflags; + lb = &tdev->line_in; + } + else { + state->_of = tdev->oflags; + lb = &tdev->line_out; + } + + state->inbuf = lb->current; + state->outbuf = lb->next; + state->active_line = lb; } -static inline int must_inline optimize("-fipa-cp-clone") -lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out) +static inline void +raise_sig(struct lcntl_state* state, int sig) { - struct rbuffer* raw = lbuf->current; - struct rbuffer* cooked = lbuf->next; - struct rbuffer* output = tdev->line_out.current; + term_sendsig(state->tdev, sig); + lcntl_raise_line_event(state, LEVT_SIGRAISE); +} - int i = 0, _if = tdev->iflags & -!out, _of = tdev->oflags & -!!out, - _lf = tdev->lflags; - int allow_more = 1, latest_eol = cooked->ptr; - char c; +static inline char +__remap_character(struct lcntl_state* state, char c) +{ + if (c == '\r') { + if ((state->_if & _ICRNL) || (state->_of & _OCRNL)) { + return '\n'; + } + } + else if (c == '\n') { + if ((state->_if & _INLCR) || (state->_of & (_ONLRET))) { + return '\r'; + } + } + else if ('a' <= c && c <= 'z') { + if ((state->_if & _IUCLC)) { + return c | 0b100000; + } else if ((state->_of & _OLCUC)) { + return c & ~0b100000; + } + } + + return c; +} - int (*lcntl_slave_put)(struct term*, struct linebuffer*, char) = - tdev->lcntl->process_and_put; +static inline void +lcntl_echo_char(struct lcntl_state* state, char c) +{ + rbuffer_put(state->echobuf, c); +} + +int +__ansi_actcontrol(struct lcntl_state* state, char chr); + +static inline int must_inline +lcntl_transform_seq(struct lcntl_state* state) +{ + struct term* tdev = state->tdev; + char c; + int i = 0; + bool full = false; #define EOL tdev->cc[_VEOL] #define EOF tdev->cc[_VEOF] @@ -44,121 +99,115 @@ lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out) #define QUIT tdev->cc[_VQUIT] #define SUSP tdev->cc[_VSUSP] -#define putc_safe(rb, chr) \ - ({ \ - if (!rbuffer_put_nof(rb, chr)) { \ - break; \ - } \ - }) + while (!lcntl_test_flag(state, LCNTLF_STOP)) + { + lcntl_unset_flag(state, LCNTLF_SPECIAL_CHAR); - if (!out) { - // Keep all cc's (except VMIN & VTIME) up to L2 cache. - for (size_t i = 0; i < _VMIN; i++) { - prefetch_rd(&tdev->cc[i], 2); + if (!rbuffer_get(state->inbuf, &c)) { + break; } - } - while (allow_more && rbuffer_get(raw, &c)) { - - if (c == '\r' && ((_if & _ICRNL) || (_of & _OCRNL))) { - c = '\n'; - } else if (c == '\n') { - if ((_if & _INLCR) || (_of & (_ONLRET))) { - c = '\r'; - } - } + c = __remap_character(state, c); if (c == '\0') { - if ((_if & _IGNBRK)) { + if ((state->_if & _IGNBRK)) { continue; } - if ((_if & _BRKINT)) { - raise_sig(tdev, lbuf, SIGINT); + if ((state->_if & _BRKINT)) { + raise_sig(state, SIGINT); break; } } - if ('a' <= c && c <= 'z') { - if ((_if & _IUCLC)) { - c = c | 0b100000; - } else if ((_of & _OLCUC)) { - c = c & ~0b100000; - } - } - - if (out) { + if (lcntl_outbound(state)) { goto do_out; } if (c == '\n') { - latest_eol = cooked->ptr + 1; - if ((_lf & _ECHONL)) { - rbuffer_put(output, c); + if (lcntl_check_echo(state, _ECHONL)) { + lcntl_echo_char(state, c); } } // For input procesing + lcntl_set_flag(state, LCNTLF_SPECIAL_CHAR); + if (c == '\n' || c == EOL) { - lbuf->sflags |= LSTATE_EOL; - } else if (c == EOF) { - lbuf->sflags |= LSTATE_EOF; - rbuffer_clear(raw); - break; - } else if (c == INTR) { - raise_sig(tdev, lbuf, SIGINT); - } else if (c == QUIT) { - raise_sig(tdev, lbuf, SIGKILL); - break; - } else if (c == SUSP) { - raise_sig(tdev, lbuf, SIGSTOP); - } else if (c == ERASE) { - if (!rbuffer_erase(cooked)) - continue; - } else if (c == KILL) { - // TODO shrink the rbuffer - } else { - goto keep; + lcntl_raise_line_event(state, LEVT_EOL); } - - if ((_lf & _ECHOE) && c == ERASE) { - rbuffer_put(output, '\x8'); - rbuffer_put(output, ' '); - rbuffer_put(output, '\x8'); + else if (c == EOF) { + lcntl_raise_line_event(state, LEVT_EOF); + lcntl_set_flag(state, LCNTLF_CLEAR_INBUF); + lcntl_set_flag(state, LCNTLF_STOP); } - if ((_lf & _ECHOK) && c == KILL) { - rbuffer_put(output, c); - rbuffer_put(output, '\n'); + else if (c == INTR) { + raise_sig(state, SIGINT); + lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF); } - - continue; - - keep: - if ((_lf & _ECHO)) { - rbuffer_put(output, c); + else if (c == QUIT) { + raise_sig(state, SIGKILL); + lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF); + lcntl_set_flag(state, LCNTLF_STOP); + } + else if (c == SUSP) { + raise_sig(state, SIGSTOP); + } + else if (c == ERASE) { + if (rbuffer_erase(state->outbuf) && + lcntl_check_echo(state, _ECHOE)) + { + lcntl_echo_char(state, '\x8'); + lcntl_echo_char(state, ' '); + lcntl_echo_char(state, '\x8'); + } + continue; + } + else if (c == KILL) { + lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF); + } + else { + lcntl_unset_flag(state, LCNTLF_SPECIAL_CHAR); } - goto put_char; + if (lcntl_check_echo(state, _ECHOK) && c == KILL) { + lcntl_echo_char(state, c); + lcntl_echo_char(state, '\n'); + } do_out: - if (c == '\n' && (_of & _ONLCR)) { - putc_safe(cooked, '\r'); + if (c == '\n' && (state->_of & _ONLCR)) { + full = !rbuffer_put_nof(state->outbuf, '\r'); } - put_char: - if (!out && (_lf & _IEXTEN) && lcntl_slave_put) { - allow_more = lcntl_slave_put(tdev, lbuf, c); - } else { - allow_more = rbuffer_put_nof(cooked, c); + if (!full) { + if (lcntl_inbound(state) && (state->_lf & _IEXTEN)) { + full = !__ansi_actcontrol(state, c); + } + else { + full = !lcntl_put_char(state, c); + } + } + + if (lcntl_test_flag(state, LCNTLF_CLEAR_INBUF)) { + rbuffer_clear(state->inbuf); + lcntl_unset_flag(state, LCNTLF_CLEAR_INBUF); + } + + if (lcntl_test_flag(state, LCNTLF_CLEAR_OUTBUF)) { + rbuffer_clear(state->outbuf); + lcntl_unset_flag(state, LCNTLF_CLEAR_OUTBUF); } + + i++; } - if (!out && !rbuffer_empty(output) && !(_lf & _NOFLSH)) { + if (state->direction != OUTBOUND && !(state->_lf & _NOFLSH)) { term_flush(tdev); } - line_flip(lbuf); + line_flip(state->active_line); return i; } @@ -166,11 +215,31 @@ lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out) int lcntl_transform_inseq(struct term* tdev) { - return lcntl_transform_seq(tdev, &tdev->line_in, false); + struct lcntl_state state; + + init_lcntl_state(&state, tdev, INBOUND); + return lcntl_transform_seq(&state); } int lcntl_transform_outseq(struct term* tdev) { - return lcntl_transform_seq(tdev, &tdev->line_out, true); + struct lcntl_state state; + + init_lcntl_state(&state, tdev, OUTBOUND); + return lcntl_transform_seq(&state); +} + +int +lcntl_put_char(struct lcntl_state* state, char c) +{ + if (lcntl_check_echo(state, _ECHO)) { + lcntl_echo_char(state, c); + } + + if (!lcntl_test_flag(state, LCNTLF_SPECIAL_CHAR)) { + return rbuffer_put_nof(state->outbuf, c); + } + + return 1; } \ No newline at end of file diff --git a/lunaix-os/hal/term/lcntls/lcntl.h b/lunaix-os/hal/term/lcntls/lcntl.h new file mode 100644 index 0000000..f867fa1 --- /dev/null +++ b/lunaix-os/hal/term/lcntls/lcntl.h @@ -0,0 +1,77 @@ +#ifndef __LUNAIX_LCNTL_H +#define __LUNAIX_LCNTL_H + +#include + +#define LCNTLF_SPECIAL_CHAR 0b000001 +#define LCNTLF_CLEAR_INBUF 0b000010 +#define LCNTLF_CLEAR_OUTBUF 0b000100 +#define LCNTLF_STOP 0b001000 + +enum lcntl_dir { + INBOUND, + OUTBOUND +}; + +struct lcntl_state { + struct term* tdev; + tcflag_t _if; // iflags + tcflag_t _of; // oflags + tcflag_t _lf; // local flags + tcflag_t _cf; // control flags + tcflag_t _sf; // state flags + enum lcntl_dir direction; + + struct linebuffer* active_line; + struct rbuffer* inbuf; + struct rbuffer* outbuf; + struct rbuffer* echobuf; +}; + +int +lcntl_put_char(struct lcntl_state* state, char c); + +static inline void +lcntl_set_flag(struct lcntl_state* state, int flags) +{ + state->_sf |= flags; +} + +static inline void +lcntl_raise_line_event(struct lcntl_state* state, int event) +{ + state->active_line->sflags |= event; +} + +static inline void +lcntl_unset_flag(struct lcntl_state* state, int flags) +{ + state->_sf &= ~flags; +} + +static inline bool +lcntl_test_flag(struct lcntl_state* state, int flags) +{ + return !!(state->_sf & flags); +} + +static inline bool +lcntl_outbound(struct lcntl_state* state) +{ + return (state->direction == OUTBOUND); +} + +static inline bool +lcntl_inbound(struct lcntl_state* state) +{ + return (state->direction == INBOUND); +} + +static inline bool +lcntl_check_echo(struct lcntl_state* state, int echo_type) +{ + return lcntl_inbound(state) && (state->_lf & echo_type); +} + + +#endif /* __LUNAIX_LCNTL_H */ diff --git a/lunaix-os/hal/term/term.c b/lunaix-os/hal/term/term.c index 3db8759..9f65d38 100644 --- a/lunaix-os/hal/term/term.c +++ b/lunaix-os/hal/term/term.c @@ -8,15 +8,11 @@ #include -#define ANSI_LCNTL 0 #define termdev(dev) ((struct term*)(dev)->underlay) -extern struct term_lcntl ansi_line_controller; -static struct term_lcntl* line_controls[] = {[ANSI_LCNTL] = - &ansi_line_controller}; #define LCNTL_TABLE_LEN (sizeof(line_controls) / sizeof(struct term_lcntl*)) -static struct devclass termdev = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM); +static struct devclass termdev_class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM); struct device* sysconsole = NULL; @@ -85,7 +81,9 @@ term_exec_cmd(struct device* dev, u32_t req, va_list args) tios->c_baud = term->iospeed; } break; case TDEV_TCSETATTR: { + struct termport_cap_ops* cap_ops; struct termios* tios = va_arg(args, struct termios*); + term->iflags = tios->c_iflag; term->oflags = tios->c_oflag; term->lflags = tios->c_lflag; @@ -98,14 +96,16 @@ term_exec_cmd(struct device* dev, u32_t req, va_list args) goto done; } + cap_ops = term->tp_cap->cap_ops; + if (tios->c_baud != term->iospeed) { term->iospeed = tios->c_baud; - term->tp_cap->set_speed(term->chdev, tios->c_baud); + cap_ops->set_speed(term->chdev, tios->c_baud); } if (old_cf != tios->c_cflag) { - term->tp_cap->set_cntrl_mode(term->chdev, tios->c_cflag); + cap_ops->set_cntrl_mode(term->chdev, tios->c_cflag); } } break; default: @@ -146,16 +146,14 @@ tdev_do_read(struct device* dev, void* buf, off_t fpos, size_t len) lbuf_ref_t current = ref_current(&tdev->line_in); bool cont = true; size_t rdsz = 0; - while (cont && rdsz < len) { - if (rbuffer_empty(deref(current))) { - tdev->line_in.sflags = 0; - cont = term_read(tdev); - } + while (cont && rdsz < len) { + cont = term_read(tdev); rdsz += rbuffer_gets( deref(current), &((char*)buf)[rdsz], len - rdsz); } - + + tdev->line_in.sflags = 0; return rdsz; } @@ -167,6 +165,7 @@ load_default_setting(struct term* tdev) tdev->lflags = _ICANON | _IEXTEN | _ISIG | _ECHO | _ECHOE | _ECHONL; tdev->iflags = _ICRNL | _IGNBRK; tdev->oflags = _ONLCR | _OPOST; + tdev->iospeed = _B9600; memcpy(tdev->cc, default_cc, _NCCS * sizeof(cc_t)); } @@ -181,38 +180,46 @@ alloc_term_buffer(struct term* terminal, size_t sz_hlf) struct term* term_create(struct device* chardev, char* suffix) { - struct term* terminal = vzalloc(sizeof(struct term)); + struct term* terminal; + struct device* tdev; + struct capability_meta* termport_cap; + struct capability_meta* tios_cap; + terminal = vzalloc(sizeof(struct term)); if (!terminal) { return NULL; } - terminal->dev = device_allocseq(NULL, terminal); + tdev = device_allocseq(NULL, terminal); + terminal->dev = tdev; terminal->chdev = chardev; - terminal->dev->ops.read = tdev_do_read; - terminal->dev->ops.write = tdev_do_write; - terminal->dev->ops.exec_cmd = term_exec_cmd; + tdev->ops.read = tdev_do_read; + tdev->ops.write = tdev_do_write; + tdev->ops.exec_cmd = term_exec_cmd; - // TODO choice of lcntl can be flexible - terminal->lcntl = line_controls[ANSI_LCNTL]; + waitq_init(&terminal->line_in_event); alloc_term_buffer(terminal, 1024); if (chardev) { int cdev_var = DEV_VAR_FROM(chardev->ident.unique); - register_device(terminal->dev, &termdev, "tty%s%d", suffix, cdev_var); + register_device(tdev, &termdev_class, "tty%s%d", suffix, cdev_var); } else { - register_device(terminal->dev, &termdev, "tty%d", termdev.variant++); + register_device(tdev, &termdev_class, "tty%d", termdev_class.variant++); } - struct capability_meta* termport_cap = device_get_capability(chardev, TERMPORT_CAP); + termport_cap = device_get_capability(chardev, TERMPORT_CAP); if (termport_cap) { - terminal->tp_cap = get_capability(termport_cap, struct termport_capability); + terminal->tp_cap = + get_capability(termport_cap, struct termport_capability); + + assert(terminal->tp_cap->cap_ops); + terminal->tp_cap->term = terminal; } - struct capability_meta* term_cap = new_capability_marker(TERMIOS_CAP); - device_grant_capability(terminal->dev, term_cap); + tios_cap = new_capability_marker(TERMIOS_CAP); + device_grant_capability(tdev, tios_cap); load_default_setting(terminal); @@ -253,6 +260,6 @@ void term_sendsig(struct term* tdev, int signal) { if ((tdev->lflags & _ISIG)) { - proc_setsignal(get_process(tdev->fggrp), signal); + signal_send(-tdev->fggrp, signal); } } \ No newline at end of file diff --git a/lunaix-os/hal/term/term_io.c b/lunaix-os/hal/term/term_io.c index b1115c8..cb93c4e 100644 --- a/lunaix-os/hal/term/term_io.c +++ b/lunaix-os/hal/term/term_io.c @@ -5,77 +5,45 @@ #include -#define ONBREAK (LSTATE_EOF | LSTATE_SIGRAISE) -#define ONSTOP (LSTATE_SIGRAISE | LSTATE_EOL | LSTATE_EOF) +#define ONBREAK (LEVT_EOF | LEVT_SIGRAISE) +#define ONSTOP (LEVT_SIGRAISE | LEVT_EOL | LEVT_EOF) static int do_read_raw(struct term* tdev) { - struct device* chdev = tdev->chdev; - - struct linebuffer* line_in = &tdev->line_in; - size_t max_lb_sz = line_in->sz_hlf; - - line_flip(line_in); - - char* inbuffer = line_in->current->buffer; - size_t min = tdev->cc[_VMIN] - 1; - size_t sz = chdev->ops.read_async(chdev, inbuffer, 0, max_lb_sz); - time_t t = clock_systime(), dt = 0; - time_t expr = (tdev->cc[_VTIME] * 100) - 1; - + struct linebuffer* line_in; + lbuf_ref_t current_buf; + size_t min, sz = 0; + time_t t, expr, dt = 0; + + line_in = &tdev->line_in; + current_buf = ref_current(line_in); + + min = tdev->cc[_VMIN] - 1; + t = clock_systime(); + expr = (tdev->cc[_VTIME] * 100) - 1; + + min = MIN(min, (size_t)line_in->sz_hlf); while (sz <= min && dt <= expr) { // XXX should we held the device lock while we are waiting? sched_pass(); dt = clock_systime() - t; t += dt; - max_lb_sz -= sz; - - // TODO pass a flags to read to indicate it is non blocking ops - sz += chdev->ops.read_async(chdev, &inbuffer[sz], 0, max_lb_sz); + sz = deref(current_buf)->len; } - rbuffer_puts(line_in->next, inbuffer, sz); - line_flip(line_in); - return 0; } -static int -do_read_raw_canno(struct term* tdev) -{ - struct device* chdev = tdev->chdev; - struct linebuffer* line_in = &tdev->line_in; - struct rbuffer* current_buf = line_in->current; - int sz = chdev->ops.read(chdev, current_buf->buffer, 0, line_in->sz_hlf); - - current_buf->ptr = sz; - current_buf->len = sz; - - return sz; -} - -static int -term_read_noncano(struct term* tdev) -{ - struct device* chdev = tdev->chdev; - return do_read_raw(tdev); -} - -static int +static inline int term_read_cano(struct term* tdev) { - struct device* chdev = tdev->chdev; - struct linebuffer* line_in = &tdev->line_in; - int size = 0; + struct linebuffer* line_in; + line_in = &tdev->line_in; while (!(line_in->sflags & ONSTOP)) { - // move all hold-out content to 'next' buffer - line_flip(line_in); - - size += do_read_raw_canno(tdev); - lcntl_transform_inseq(tdev); + pwait(&tdev->line_in_event); } return 0; @@ -87,18 +55,22 @@ term_read(struct term* tdev) if ((tdev->lflags & _ICANON)) { return term_read_cano(tdev); } - return term_read_noncano(tdev); + + return do_read_raw(tdev); } int term_flush(struct term* tdev) { + struct device* chardev; struct linebuffer* line_out = &tdev->line_out; char* xmit_buf = tdev->scratch_pad; lbuf_ref_t current_ref = ref_current(line_out); - + int count = 0; + chardev = tdev->chdev; + while (!rbuffer_empty(deref(current_ref))) { if ((tdev->oflags & _OPOST)) { lcntl_transform_outseq(tdev); @@ -111,7 +83,7 @@ term_flush(struct term* tdev) off_t off = 0; int ret = 0; while (xmit_len && ret >= 0) { - ret = tdev->chdev->ops.write(tdev->chdev, &xmit_buf[off], 0, xmit_len); + ret = chardev->ops.write(chardev, &xmit_buf[off], 0, xmit_len); xmit_len -= ret; off += ret; count += ret; @@ -124,4 +96,34 @@ term_flush(struct term* tdev) } return count; +} + +void +term_notify_data_avaliable(struct termport_capability* cap) +{ + struct term* term; + struct device* term_chrdev; + struct linebuffer* line_in; + lbuf_ref_t current_ref; + char* buf; + int sz; + + term = cap->term; + term_chrdev = term->chdev; + line_in = &term->line_in; + current_ref = ref_current(line_in); + + // make room for current buf + line_flip(line_in); + buf = deref(current_ref)->buffer; + + sz = term_chrdev->ops.read_async(term_chrdev, buf, 0, line_in->sz_hlf); + rbuffer_setcontent(deref(current_ref), sz); + + if ((term->lflags & _ICANON)) { + lcntl_transform_inseq(term); + // write all processed to next, and flip back to current + } + + pwake_all(&term->line_in_event); } \ No newline at end of file diff --git a/lunaix-os/includes/hal/serial.h b/lunaix-os/includes/hal/serial.h index f65fd08..af345da 100644 --- a/lunaix-os/includes/hal/serial.h +++ b/lunaix-os/includes/hal/serial.h @@ -33,6 +33,8 @@ struct serial_dev struct rbuffer rxbuf; int wr_len; + struct capability_meta* tp_cap; + /** * @brief Write buffer to TX. The return code indicate * the transaction is either done in synced mode (TX_DONE) or will be diff --git a/lunaix-os/includes/hal/term.h b/lunaix-os/includes/hal/term.h index 4ddf74d..407707e 100644 --- a/lunaix-os/includes/hal/term.h +++ b/lunaix-os/includes/hal/term.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -16,21 +17,15 @@ struct linebuffer short sflags; short sz_hlf; }; -#define LSTATE_EOL (1) -#define LSTATE_EOF (1 << 1) -#define LSTATE_SIGRAISE (1 << 2) +#define LEVT_EOL (1) +#define LEVT_EOF (1 << 1) +#define LEVT_SIGRAISE (1 << 2) typedef struct rbuffer** lbuf_ref_t; #define ref_current(lbuf) (&(lbuf)->current) #define ref_next(lbuf) (&(lbuf)->next) #define deref(bref) (*(bref)) -struct term_lcntl -{ - struct term* term; - int (*process_and_put)(struct term*, struct linebuffer*, char); -}; - /** * @brief Communication port capability that a device is supported natively, * or able to emulate low level serial transmission behaviour specify @@ -46,25 +41,33 @@ struct term_lcntl */ #define TERMIOS_CAP 0x534f4954U -struct termport_capability -{ - CAPABILITY_META; +struct term; +struct termport_cap_ops +{ void (*set_speed)(struct device*, speed_t); + void (*set_clkbase)(struct device*, unsigned int); void (*set_cntrl_mode)(struct device*, tcflag_t); }; +struct termport_capability +{ + CAPABILITY_META; + struct termport_cap_ops* cap_ops; + struct term* term; +}; + struct term { struct device* dev; struct device* chdev; - struct term_lcntl* lcntl; struct linebuffer line_out; struct linebuffer line_in; char* scratch_pad; pid_t fggrp; struct termport_capability* tp_cap; + waitq_t line_in_event; /* -- POSIX.1-2008 compliant fields -- */ tcflag_t iflags; @@ -72,7 +75,11 @@ struct term tcflag_t lflags; tcflag_t cflags; cc_t cc[_NCCS]; + + /* -- END POSIX.1-2008 compliant fields -- */ speed_t iospeed; + speed_t clkbase; + tcflag_t tflags; // temp flags }; extern struct device* sysconsole; @@ -83,15 +90,6 @@ term_create(struct device* chardev, char* suffix); int term_bind(struct term* tdev, struct device* chdev); -int -term_push_lcntl(struct term* tdev, struct term_lcntl* lcntl); - -int -term_pop_lcntl(struct term* tdev); - -struct term_lcntl* -term_get_lcntl(u32_t lcntl_index); - static inline void line_flip(struct linebuffer* lbf) { @@ -121,4 +119,20 @@ lcntl_transform_inseq(struct term* tdev); int lcntl_transform_outseq(struct term* tdev); +static inline void +term_cap_set_operations(struct termport_capability* cap, + struct termport_cap_ops* ops) +{ + cap->cap_ops = ops; +} + +void +term_notify_data_avaliable(struct termport_capability* cap); + +#define termport_default_ops \ + ({ \ + extern struct termport_cap_ops default_termport_cap_ops;\ + &default_termport_cap_ops; \ + }) + #endif /* __LUNAIX_TERM_H */ diff --git a/lunaix-os/includes/lunaix/ds/rbuffer.h b/lunaix-os/includes/lunaix/ds/rbuffer.h index d45c9fd..ffbb99b 100644 --- a/lunaix-os/includes/lunaix/ds/rbuffer.h +++ b/lunaix-os/includes/lunaix/ds/rbuffer.h @@ -30,11 +30,22 @@ int rbuffer_puts(struct rbuffer* rb, char* c, size_t len); int -rbuffer_gets(struct rbuffer* rb, char* buf, size_t len); +rbuffer_gets_opt(struct rbuffer* rb, char* buf, size_t len, bool consumed); int rbuffer_get(struct rbuffer* rb, char* c); +static inline int +rbuffer_gets(struct rbuffer* rb, char* buf, size_t len) +{ + return rbuffer_gets_opt(rb, buf, len, true); +} + +static inline int +rbuffer_gets_no_consume(struct rbuffer* rb, char* buf, size_t len) +{ + return rbuffer_gets_opt(rb, buf, len, false); +} static inline void rbuffer_clear(struct rbuffer* rb) @@ -48,6 +59,19 @@ rbuffer_empty(struct rbuffer* rb) return rb->len == 0; } +static inline unsigned int +rbuffer_len(struct rbuffer* rb) +{ + return rb->len; +} + +static inline void +rbuffer_setcontent(struct rbuffer* rb, size_t content_len) +{ + rb->ptr = content_len; + rb->len = content_len; +} + static inline bool rbuffer_full(struct rbuffer* rb) { diff --git a/lunaix-os/includes/usr/lunaix/serial.h b/lunaix-os/includes/usr/lunaix/serial.h index c01bb15..6f73155 100644 --- a/lunaix-os/includes/usr/lunaix/serial.h +++ b/lunaix-os/includes/usr/lunaix/serial.h @@ -3,13 +3,14 @@ #include "ioctl_defs.h" -#define SERIO_RXEN IOREQ(1, 0) -#define SERIO_RXDA IOREQ(2, 0) +#define SERIO_RXEN IOREQ(1, 0) +#define SERIO_RXDA IOREQ(2, 0) -#define SERIO_TXEN IOREQ(3, 0) -#define SERIO_TXDA IOREQ(4, 0) +#define SERIO_TXEN IOREQ(3, 0) +#define SERIO_TXDA IOREQ(4, 0) -#define SERIO_SETBRDIV IOREQ(5, 0) -#define SERIO_SETCNTRLMODE IOREQ(6, 0) +#define SERIO_SETBRDRATE IOREQ(5, 0) +#define SERIO_SETCNTRLMODE IOREQ(6, 0) +#define SERIO_SETBRDBASE IOREQ(7, 0) #endif /* __LUNAIX_USERIAL_H */ diff --git a/lunaix-os/kernel/LBuild b/lunaix-os/kernel/LBuild index b52bc29..600b512 100644 --- a/lunaix-os/kernel/LBuild +++ b/lunaix-os/kernel/LBuild @@ -13,7 +13,6 @@ sources([ "kinit.c", "lunad.c", "spike.c", - "tty/tty.c", "kprint/kp_records.c", "kprint/kprintf.c", "time/clock.c", diff --git a/lunaix-os/kernel/ds/rbuffer.c b/lunaix-os/kernel/ds/rbuffer.c index eea75d6..82d1402 100644 --- a/lunaix-os/kernel/ds/rbuffer.c +++ b/lunaix-os/kernel/ds/rbuffer.c @@ -61,7 +61,7 @@ rbuffer_puts(struct rbuffer* rb, char* buf, size_t len) } int -rbuffer_gets(struct rbuffer* rb, char* buf, size_t len) +rbuffer_gets_opt(struct rbuffer* rb, char* buf, size_t len, bool consumed) { if (!len || !rb->len) return 0; @@ -79,7 +79,9 @@ rbuffer_gets(struct rbuffer* rb, char* buf, size_t len) memcpy(&buf[-nlen], &rb->buffer[ptr_start], nlen); } - rb->len -= nlen; + if (consumed) { + rb->len -= nlen; + } return nlen; } diff --git a/lunaix-os/kernel/kinit.c b/lunaix-os/kernel/kinit.c index ca28001..24550cf 100644 --- a/lunaix-os/kernel/kinit.c +++ b/lunaix-os/kernel/kinit.c @@ -43,14 +43,9 @@ kernel_bootstrap(struct boot_handoff* bhctx) /* Begin kernel bootstrapping sequence */ boot_begin(bhctx); - tty_init((void*)ioremap(0xB8000, PAGE_SIZE)); - /* Setup kernel memory layout and services */ kmem_init(bhctx); - // FIXME this goes to hal/gfxa - tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK); - boot_parse_cmdline(bhctx); /* Prepare stack trace environment */ diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index 91cf61b..82a2aa9 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -33,6 +33,8 @@ struct scheduler sched_ctx; struct cake_pile *proc_pile ,*thread_pile; +#define root_process (sched_ctx.procs[1]) + LOG_MODULE("SCHED") void @@ -256,7 +258,6 @@ __DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds) bed->alarm_time = seconds ? now + seconds : 0; - struct proc_info* root_proc = sched_ctx.procs[0]; if (llist_empty(&bed->sleepers)) { llist_append(&sched_ctx.sleepers, &bed->sleepers); } @@ -435,7 +436,7 @@ commit_process(struct proc_info* process) // every process is the child of first process (pid=1) if (!process->parent) { if (likely(!kernel_process(process))) { - process->parent = sched_ctx.procs[1]; + process->parent = root_process; } else { process->parent = process; } @@ -474,6 +475,20 @@ destory_thread(struct thread* thread) cake_release(thread_pile, thread); } +static void +orphan_children(struct proc_info* proc) +{ + struct proc_info *root; + struct proc_info *pos, *n; + + root = root_process; + + llist_for_each(pos, n, &proc->children, siblings) { + pos->parent = root; + llist_append(&root->children, &pos->siblings); + } +} + void delete_process(struct proc_info* proc) { @@ -520,6 +535,8 @@ delete_process(struct proc_info* proc) destory_thread(pos); } + orphan_children(proc); + procvm_unmount_release(mm); cake_release(proc_pile, proc); diff --git a/lunaix-os/kernel/process/signal.c b/lunaix-os/kernel/process/signal.c index e40526e..eef5c7b 100644 --- a/lunaix-os/kernel/process/signal.c +++ b/lunaix-os/kernel/process/signal.c @@ -147,8 +147,7 @@ int signal_send(pid_t pid, signum_t signum) { if (signum >= _SIG_NUM) { - syscall_result(EINVAL); - return -1; + return EINVAL; } pid_t sender_pid = __current->pid; @@ -166,8 +165,7 @@ signal_send(pid_t pid, signum_t signum) } else { // TODO: send to all process. // But I don't want to support it yet. - syscall_result(EINVAL); - return -1; + return EINVAL; } send_grp: ; @@ -179,8 +177,7 @@ send_grp: ; send_single: if (proc_terminated(proc)) { - syscall_result(EINVAL); - return -1; + return EINVAL; } proc_setsignal(proc, signum); @@ -358,7 +355,7 @@ __DEFINE_LXSYSCALL(int, pause) __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum) { - return signal_send(pid, signum); + return syscall_result(signal_send(pid, signum)); } __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset) diff --git a/lunaix-os/usr/init/init.c b/lunaix-os/usr/init/init.c index 2416e07..47fcf68 100644 --- a/lunaix-os/usr/init/init.c +++ b/lunaix-os/usr/init/init.c @@ -36,6 +36,9 @@ init_termios(int fd) { term.c_oflag = ONLCR | OPOST; term.c_cflag = CREAD | CLOCAL | CS8 | CPARENB; term.c_cc[VERASE] = 0x7f; + + cfsetispeed(&term, B9600); + cfsetospeed(&term, B9600); check(tcsetattr(fd, 0, &term)); diff --git a/lunaix-os/usr/libc/includes/termios.h b/lunaix-os/usr/libc/includes/termios.h index 42ad0ac..abdcf85 100644 --- a/lunaix-os/usr/libc/includes/termios.h +++ b/lunaix-os/usr/libc/includes/termios.h @@ -89,12 +89,20 @@ static inline speed_t cfgetospeed(const struct termios* termios) { return termio static inline int cfsetispeed(struct termios* termios, speed_t baud) { + if (baud > B38400) { + return -1; + } + termios->c_baud = baud; return 0; } static inline int cfsetospeed(struct termios* termios, speed_t baud) { + if (baud > B38400) { + return -1; + } + termios->c_baud = baud; return 0; } @@ -110,5 +118,4 @@ int tcgetattr(int, struct termios *); int tcsendbreak(int, int); int tcsetattr(int, int, const struct termios *); - #endif /* __LUNAIX_TERMIOS_H */ diff --git a/lunaix-os/usr/sh/sh.c b/lunaix-os/usr/sh/sh.c index 2ac473a..c2c8347 100644 --- a/lunaix-os/usr/sh/sh.c +++ b/lunaix-os/usr/sh/sh.c @@ -132,6 +132,27 @@ sh_exec(const char** argv) waitpid(p, NULL, 0); } +static char* +sanity_filter(char* buf) +{ + int off = 0, i = 0; + char c; + do { + c = buf[i]; + + if ((32 <= c && c <= 126) || !c) { + buf[i - off] = c; + } + else { + off++; + } + + i++; + } while(c); + + return buf; +} + void sh_loop() { @@ -157,6 +178,7 @@ sh_loop() } buf[sz] = '\0'; + sanity_filter(buf); // currently, this shell only support single argument if (!parse_cmdline(buf, argv)) { -- 2.27.0