mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add termios(2).
This commit is contained in:
parent
8f233b4a10
commit
bff1265d62
39 changed files with 1685 additions and 298 deletions
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/termmode.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
@ -145,7 +146,17 @@ int child()
|
|||
setenv("INIT_PID", init_pid_str, 1);
|
||||
|
||||
setpgid(0, 0);
|
||||
tcsetpgrp(0, getpid());
|
||||
|
||||
sigset_t oldset, sigs;
|
||||
sigemptyset(&sigs);
|
||||
sigaddset(&sigs, SIGTTOU);
|
||||
sigprocmask(SIG_BLOCK, &sigs, &oldset);
|
||||
tcsetpgrp(0, getpgid(0));
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
|
||||
unsigned int termmode = 0;
|
||||
gettermmode(0, &termmode);
|
||||
settermmode(0, termmode & ~TERMMODE_DISABLE);
|
||||
|
||||
const char* default_shell = "sh";
|
||||
const char* default_home = "/root";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015, 2016.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -110,7 +110,7 @@ void PrintChar(char c)
|
|||
{
|
||||
if ( c == '\n' )
|
||||
Newline();
|
||||
else if ( c == '\b' )
|
||||
else if ( c == '\b' || c == 127 )
|
||||
{
|
||||
if ( column )
|
||||
column--;
|
||||
|
@ -290,11 +290,11 @@ void ReadCommand(char* buffer, size_t buffer_length)
|
|||
continue;
|
||||
|
||||
// Handle backspace.
|
||||
if ( c == '\b' )
|
||||
if ( c == '\b' || c == 127 )
|
||||
{
|
||||
if ( !written )
|
||||
continue;
|
||||
PrintChar(c);
|
||||
PrintChar('\b');
|
||||
written--;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -828,4 +828,39 @@ Ref<Descriptor> Descriptor::fsm_mount(ioctx_t* ctx,
|
|||
return result;
|
||||
}
|
||||
|
||||
int Descriptor::tcdrain(ioctx_t* ctx)
|
||||
{
|
||||
return vnode->tcdrain(ctx);
|
||||
}
|
||||
|
||||
int Descriptor::tcflow(ioctx_t* ctx, int action)
|
||||
{
|
||||
return vnode->tcflow(ctx, action);
|
||||
}
|
||||
|
||||
int Descriptor::tcflush(ioctx_t* ctx, int queue_selector)
|
||||
{
|
||||
return vnode->tcflush(ctx, queue_selector);
|
||||
}
|
||||
|
||||
int Descriptor::tcgetattr(ioctx_t* ctx, struct termios* tio)
|
||||
{
|
||||
return vnode->tcgetattr(ctx, tio);
|
||||
}
|
||||
|
||||
pid_t Descriptor::tcgetsid(ioctx_t* ctx)
|
||||
{
|
||||
return vnode->tcgetsid(ctx);
|
||||
}
|
||||
|
||||
int Descriptor::tcsendbreak(ioctx_t* ctx, int duration)
|
||||
{
|
||||
return vnode->tcsendbreak(ctx, duration);
|
||||
}
|
||||
|
||||
int Descriptor::tcsetattr(ioctx_t* ctx, int actions, const struct termios* tio)
|
||||
{
|
||||
return vnode->tcsetattr(ctx, actions, tio);
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
#include <sortix/dirent.h>
|
||||
#include <sortix/fcntl.h>
|
||||
#include <sortix/stat.h>
|
||||
#include <sortix/termios.h>
|
||||
#include <sortix/timespec.h>
|
||||
#include <sortix/winsize.h>
|
||||
|
||||
#include <fsmarshall-msg.h>
|
||||
|
||||
|
@ -255,6 +255,13 @@ public:
|
|||
virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count);
|
||||
virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count);
|
||||
virtual int unmounted(ioctx_t* ctx);
|
||||
virtual int tcdrain(ioctx_t* ctx);
|
||||
virtual int tcflow(ioctx_t* ctx, int action);
|
||||
virtual int tcflush(ioctx_t* ctx, int queue_selector);
|
||||
virtual int tcgetattr(ioctx_t* ctx, struct termios* tio);
|
||||
virtual pid_t tcgetsid(ioctx_t* ctx);
|
||||
virtual int tcsendbreak(ioctx_t* ctx, int duration);
|
||||
virtual int tcsetattr(ioctx_t* ctx, int actions, const struct termios* tio);
|
||||
|
||||
private:
|
||||
bool SendMessage(Channel* channel, size_t type, void* ptr, size_t size,
|
||||
|
@ -1472,6 +1479,120 @@ int Unode::unmounted(ioctx_t* /*ctx*/)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int Unode::tcdrain(ioctx_t* ctx)
|
||||
{
|
||||
Channel* channel = server->Connect(ctx);
|
||||
if ( !channel )
|
||||
return -1;
|
||||
int ret = -1;
|
||||
struct fsm_req_tcdrain msg;
|
||||
msg.ino = ino;
|
||||
if ( SendMessage(channel, FSM_REQ_TCDRAIN, &msg, sizeof(msg)) &&
|
||||
RecvMessage(channel, FSM_RESP_SUCCESS, NULL, 0) )
|
||||
ret = 0;
|
||||
channel->KernelClose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Unode::tcflow(ioctx_t* ctx, int action)
|
||||
{
|
||||
Channel* channel = server->Connect(ctx);
|
||||
if ( !channel )
|
||||
return -1;
|
||||
int ret = -1;
|
||||
struct fsm_req_tcflow msg;
|
||||
msg.ino = ino;
|
||||
msg.action = action;
|
||||
if ( SendMessage(channel, FSM_REQ_TCFLOW, &msg, sizeof(msg)) &&
|
||||
RecvMessage(channel, FSM_RESP_SUCCESS, NULL, 0) )
|
||||
ret = 0;
|
||||
channel->KernelClose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Unode::tcflush(ioctx_t* ctx, int queue_selector)
|
||||
{
|
||||
Channel* channel = server->Connect(ctx);
|
||||
if ( !channel )
|
||||
return -1;
|
||||
int ret = -1;
|
||||
struct fsm_req_tcflush msg;
|
||||
msg.ino = ino;
|
||||
msg.queue_selector = queue_selector;
|
||||
if ( SendMessage(channel, FSM_REQ_TCFLUSH, &msg, sizeof(msg)) &&
|
||||
RecvMessage(channel, FSM_RESP_SUCCESS, NULL, 0) )
|
||||
ret = 0;
|
||||
channel->KernelClose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Unode::tcgetattr(ioctx_t* ctx, struct termios* io_tio)
|
||||
{
|
||||
Channel* channel = server->Connect(ctx);
|
||||
if ( !channel )
|
||||
return -1;
|
||||
int ret = -1;
|
||||
struct fsm_req_tcgetattr msg;
|
||||
struct fsm_resp_tcgetattr resp;
|
||||
msg.ino = ino;
|
||||
if ( SendMessage(channel, FSM_REQ_TCGETATTR, &msg, sizeof(msg)) &&
|
||||
RecvMessage(channel, FSM_RESP_TCGETATTR, &msg, sizeof(msg)) &&
|
||||
ctx->copy_to_dest(io_tio, &resp.tio, sizeof(resp.tio)) )
|
||||
ret = 0;
|
||||
channel->KernelClose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
pid_t Unode::tcgetsid(ioctx_t* ctx)
|
||||
{
|
||||
Channel* channel = server->Connect(ctx);
|
||||
if ( !channel )
|
||||
return -1;
|
||||
pid_t ret = -1;
|
||||
struct fsm_req_tcgetsid msg;
|
||||
struct fsm_resp_tcgetsid resp;
|
||||
msg.ino = ino;
|
||||
if ( SendMessage(channel, FSM_REQ_TCGETSID, &msg, sizeof(msg)) &&
|
||||
RecvMessage(channel, FSM_RESP_TCGETSID, &msg, sizeof(msg)) )
|
||||
ret = resp.sid;
|
||||
channel->KernelClose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Unode::tcsendbreak(ioctx_t* ctx, int duration)
|
||||
{
|
||||
Channel* channel = server->Connect(ctx);
|
||||
if ( !channel )
|
||||
return -1;
|
||||
int ret = -1;
|
||||
struct fsm_req_tcsendbreak msg;
|
||||
msg.ino = ino;
|
||||
msg.duration = duration;
|
||||
if ( SendMessage(channel, FSM_REQ_TCSENDBREAK, &msg, sizeof(msg)) &&
|
||||
RecvMessage(channel, FSM_RESP_SUCCESS, NULL, 0) )
|
||||
ret = 0;
|
||||
channel->KernelClose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Unode::tcsetattr(ioctx_t* ctx, int actions, const struct termios* user_tio)
|
||||
{
|
||||
struct fsm_req_tcsetattr msg;
|
||||
if ( !ctx->copy_from_src(&msg.tio, user_tio, sizeof(msg.tio)) )
|
||||
return -1;
|
||||
Channel* channel = server->Connect(ctx);
|
||||
if ( !channel )
|
||||
return -1;
|
||||
int ret = -1;
|
||||
msg.ino = ino;
|
||||
msg.actions = actions;
|
||||
if ( SendMessage(channel, FSM_REQ_TCSETATTR, &msg, sizeof(msg)) &&
|
||||
RecvMessage(channel, FSM_RESP_SUCCESS, NULL, 0) )
|
||||
ret = 0;
|
||||
channel->KernelClose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Bootstrap(Ref<Inode>* out_root,
|
||||
Ref<Inode>* out_server,
|
||||
const struct stat* rootst)
|
||||
|
|
41
kernel/include/sortix/ioctl.h
Normal file
41
kernel/include/sortix/ioctl.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2016.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
sortix/ioctl.h
|
||||
Miscellaneous device control interface.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef INCLUDE_SORTIX_IOCTL_H
|
||||
#define INCLUDE_SORTIX_IOCTL_H
|
||||
|
||||
#define __IOCTL_TYPE_EXP 3 /* 2^3 kinds of argument types supported.*/
|
||||
#define __IOCTL_TYPE_MASK ((1 << __IOCTL_TYPE_EXP) - 1)
|
||||
#define __IOCTL_TYPE_VOID 0
|
||||
#define __IOCTL_TYPE_INT 1
|
||||
#define __IOCTL_TYPE_LONG 2
|
||||
#define __IOCTL_TYPE_PTR 3
|
||||
/* 4-7 is unused in case of future expansion. */
|
||||
#define __IOCTL(index, type) ((index) << __IOCTL_TYPE_EXP | (type))
|
||||
#define __IOCTL_INDEX(value) ((value) >> __IOCTL_TYPE_EXP)
|
||||
#define __IOCTL_TYPE(value) ((value) & __IOCTL_TYPE_MASK)
|
||||
|
||||
#define TIOCGWINSZ __IOCTL(1, __IOCTL_TYPE_PTR)
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
|||
|
||||
struct stat;
|
||||
struct statvfs;
|
||||
struct termios;
|
||||
struct wincurpos;
|
||||
struct winsize;
|
||||
struct kernel_dirent;
|
||||
|
@ -109,6 +110,13 @@ public:
|
|||
int fsm_fsbind(ioctx_t* ctx, Ref<Descriptor> target, int flags);
|
||||
Ref<Descriptor> fsm_mount(ioctx_t* ctx, const char* filename,
|
||||
const struct stat* rootst, int flags);
|
||||
int tcdrain(ioctx_t* ctx);
|
||||
int tcflow(ioctx_t* ctx, int action);
|
||||
int tcflush(ioctx_t* ctx, int queue_selector);
|
||||
int tcgetattr(ioctx_t* ctx, struct termios* tio);
|
||||
pid_t tcgetsid(ioctx_t* ctx);
|
||||
int tcsendbreak(ioctx_t* ctx, int duration);
|
||||
int tcsetattr(ioctx_t* ctx, int actions, const struct termios* tio);
|
||||
|
||||
private:
|
||||
Ref<Descriptor> open_elem(ioctx_t* ctx, const char* filename, int flags,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
|||
|
||||
struct stat;
|
||||
struct statvfs;
|
||||
struct termios;
|
||||
struct wincurpos;
|
||||
struct winsize;
|
||||
struct kernel_dirent;
|
||||
|
@ -113,6 +114,13 @@ public:
|
|||
virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count) = 0;
|
||||
virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count) = 0;
|
||||
virtual int unmounted(ioctx_t* ctx) = 0;
|
||||
virtual int tcdrain(ioctx_t* ctx) = 0;
|
||||
virtual int tcflow(ioctx_t* ctx, int action) = 0;
|
||||
virtual int tcflush(ioctx_t* ctx, int queue_selector) = 0;
|
||||
virtual int tcgetattr(ioctx_t* ctx, struct termios* tio) = 0;
|
||||
virtual pid_t tcgetsid(ioctx_t* ctx) = 0;
|
||||
virtual int tcsendbreak(ioctx_t* ctx, int duration) = 0;
|
||||
virtual int tcsetattr(ioctx_t* ctx, int actions, const struct termios* tio) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -201,6 +209,13 @@ public:
|
|||
virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count);
|
||||
virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count);
|
||||
virtual int unmounted(ioctx_t* ctx);
|
||||
virtual int tcdrain(ioctx_t* ctx);
|
||||
virtual int tcflow(ioctx_t* ctx, int action);
|
||||
virtual int tcflush(ioctx_t* ctx, int queue_selector);
|
||||
virtual int tcgetattr(ioctx_t* ctx, struct termios* tio);
|
||||
virtual pid_t tcgetsid(ioctx_t* ctx);
|
||||
virtual int tcsendbreak(ioctx_t* ctx, int duration);
|
||||
virtual int tcsetattr(ioctx_t* ctx, int actions, const struct termios* tio);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <sortix/termios.h>
|
||||
#include <sortix/timespec.h>
|
||||
#include <sortix/tmns.h>
|
||||
#include <sortix/winsize.h>
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
|
@ -103,7 +104,7 @@ int sys_getsockopt(int, int, int, void*, size_t*);
|
|||
int sys_gettermmode(int, unsigned*);
|
||||
uid_t sys_getuid(void);
|
||||
mode_t sys_getumask(void);
|
||||
int sys_ioctl(int, int, void*);
|
||||
int sys_ioctl(int, int, uintptr_t);
|
||||
int sys_isatty(int);
|
||||
ssize_t sys_kernelinfo(const char*, char*, size_t);
|
||||
int sys_kill(pid_t, int);
|
||||
|
@ -154,10 +155,17 @@ int sys_sigpending(sigset_t*);
|
|||
int sys_sigprocmask(int, const sigset_t*, sigset_t*);
|
||||
int sys_sigsuspend(const sigset_t*);
|
||||
int sys_symlinkat(const char*, int, const char*);
|
||||
int sys_tcdrain(int);
|
||||
int sys_tcflow(int, int);
|
||||
int sys_tcflush(int, int);
|
||||
int sys_tcgetattr(int, struct termios*);
|
||||
ssize_t sys_tcgetblob(int, const char*, void*, size_t);
|
||||
int sys_tcgetpgrp(int);
|
||||
pid_t sys_tcgetsid(int);
|
||||
int sys_tcgetwincurpos(int, struct wincurpos*);
|
||||
int sys_tcgetwinsize(int, struct winsize*);
|
||||
int sys_tcsendbreak(int, int);
|
||||
int sys_tcsetattr(int, int, const struct termios*);
|
||||
ssize_t sys_tcsetblob(int, const char*, const void*, size_t);
|
||||
int sys_tcsetpgrp(int, pid_t);
|
||||
pid_t sys_tfork(int, struct tfork*);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
|||
|
||||
struct stat;
|
||||
struct statvfs;
|
||||
struct termios;
|
||||
struct wincurpos;
|
||||
struct winsize;
|
||||
struct kernel_dirent;
|
||||
|
@ -105,6 +106,13 @@ public:
|
|||
int unmount(ioctx_t* ctx, const char* filename, int flags);
|
||||
int fsm_fsbind(ioctx_t* ctx, Ref<Vnode> target, int flags);
|
||||
Ref<Vnode> fsm_mount(ioctx_t* ctx, const char* filename, const struct stat* rootst, int flags);
|
||||
int tcdrain(ioctx_t* ctx);
|
||||
int tcflow(ioctx_t* ctx, int action);
|
||||
int tcflush(ioctx_t* ctx, int queue_selector);
|
||||
int tcgetattr(ioctx_t* ctx, struct termios* tio);
|
||||
pid_t tcgetsid(ioctx_t* ctx);
|
||||
int tcsendbreak(ioctx_t* ctx, int duration);
|
||||
int tcsetattr(ioctx_t* ctx, int actions, const struct termios* tio);
|
||||
|
||||
public /*TODO: private*/:
|
||||
Ref<Inode> inode;
|
||||
|
|
|
@ -180,13 +180,13 @@
|
|||
#define SYSCALL_CLOSEFROM 152
|
||||
#define SYSCALL_RESERVED1 153
|
||||
#define SYSCALL_PSCTL 154
|
||||
#define SYSCALL_RESERVED2 155
|
||||
#define SYSCALL_RESERVED3 156
|
||||
#define SYSCALL_RESERVED4 157
|
||||
#define SYSCALL_RESERVED5 158
|
||||
#define SYSCALL_RESERVED6 159
|
||||
#define SYSCALL_RESERVED7 160
|
||||
#define SYSCALL_RESERVED8 161
|
||||
#define SYSCALL_TCDRAIN 155
|
||||
#define SYSCALL_TCFLOW 156
|
||||
#define SYSCALL_TCFLUSH 157
|
||||
#define SYSCALL_TCGETATTR 158
|
||||
#define SYSCALL_TCGETSID 159
|
||||
#define SYSCALL_TCSENDBREAK 160
|
||||
#define SYSCALL_TCSETATTR 161
|
||||
#define SYSCALL_SCRAM 162
|
||||
#define SYSCALL_MAX_NUM 163 /* index of highest constant + 1 */
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015, 2016.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
sortix/termios.h
|
||||
Defines values for termios.
|
||||
Termios types and constants.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
@ -27,34 +27,108 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sys/__/types.h>
|
||||
#define VEOF 0
|
||||
#define VEOL 1
|
||||
#define VERASE 2
|
||||
#define VINTR 3
|
||||
#define VKILL 4
|
||||
#define VMIN 5
|
||||
#define VQUIT 6
|
||||
#define VSTART 7
|
||||
#define VSTOP 8
|
||||
#define VSUSP 9
|
||||
#define VTIME 10
|
||||
#define VWERASE 11
|
||||
#define NCCS 24
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#define BRKINT (1U << 0)
|
||||
#define ICRNL (1U << 1)
|
||||
#define IGNBRK (1U << 2)
|
||||
#define IGNCR (1U << 3)
|
||||
#define IGNPAR (1U << 4)
|
||||
#define INLCR (1U << 5)
|
||||
#define INPCK (1U << 6)
|
||||
#define ISTRIP (1U << 7)
|
||||
#define IXANY (1U << 8)
|
||||
#define IXOFF (1U << 9)
|
||||
#define IXON (1U << 10)
|
||||
#define PARMRK (1U << 11)
|
||||
|
||||
#define OPOST (1U << 0)
|
||||
|
||||
#define B0 0
|
||||
#define B50 50
|
||||
#define B75 75
|
||||
#define B110 110
|
||||
#define B134 134
|
||||
#define B150 150
|
||||
#define B200 200
|
||||
#define B300 300
|
||||
#define B600 600
|
||||
#define B1200 1200
|
||||
#define B1800 1800
|
||||
#define B2400 2400
|
||||
#define B4800 4800
|
||||
#define B9600 9600
|
||||
#define B19200 19200
|
||||
#define B38400 38400
|
||||
|
||||
#define CS5 (0U << 0)
|
||||
#define CS6 (1U << 0)
|
||||
#define CS7 (2U << 0)
|
||||
#define CS8 (3U << 0)
|
||||
#define CSIZE (CS5 | CS6 | CS7 | CS8)
|
||||
#define CSTOPB (1U << 2)
|
||||
#define CREAD (1U << 3)
|
||||
#define PARENB (1U << 4)
|
||||
#define PARODD (1U << 5)
|
||||
#define HUPCL (1U << 6)
|
||||
#define CLOCAL (1U << 7)
|
||||
|
||||
#define ECHO (1U << 0)
|
||||
#define ECHOE (1U << 1)
|
||||
#define ECHOK (1U << 2)
|
||||
#define ECHONL (1U << 3)
|
||||
#define ICANON (1U << 4)
|
||||
#define IEXTEN (1U << 5)
|
||||
#define ISIG (1U << 6)
|
||||
#define NOFLSH (1U << 7)
|
||||
#define TOSTOP (1U << 8)
|
||||
/* Transitional compatibility as Sortix switches from termmode to termios. */
|
||||
#if __USE_SORTIX
|
||||
#define ISORTIX_TERMMODE (1U << 9)
|
||||
#define ISORTIX_CHARS_DISABLE (1U << 10)
|
||||
#define ISORTIX_KBKEY (1U << 11)
|
||||
#define ISORTIX_32BIT (1U << 12)
|
||||
#define ISORTIX_NONBLOCK (1U << 13)
|
||||
#endif
|
||||
|
||||
#ifndef __size_t_defined
|
||||
#define __size_t_defined
|
||||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#define TCSANOW 0
|
||||
#define TCSADRAIN 1
|
||||
#define TCSAFLUSH 2
|
||||
|
||||
struct wincurpos
|
||||
#define TCIFLUSH (1 << 0)
|
||||
#define TCOFLUSH (1 << 1)
|
||||
#define TCIOFLUSH (TCIFLUSH | TCOFLUSH)
|
||||
|
||||
#define TCIOFF 0
|
||||
#define TCION 1
|
||||
#define TCOOFF 2
|
||||
#define TCOON 3
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
struct termios
|
||||
{
|
||||
size_t wcp_row;
|
||||
size_t wcp_col;
|
||||
tcflag_t c_iflag;
|
||||
tcflag_t c_oflag;
|
||||
tcflag_t c_cflag;
|
||||
tcflag_t c_lflag;
|
||||
speed_t c_ispeed;
|
||||
speed_t c_ospeed;
|
||||
cc_t c_cc[NCCS];
|
||||
};
|
||||
|
||||
struct winsize
|
||||
{
|
||||
size_t ws_row;
|
||||
size_t ws_col;
|
||||
size_t ws_xpixel;
|
||||
size_t ws_ypixel;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2015, 2016.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -25,12 +25,16 @@
|
|||
#ifndef SORTIX_TERMMODE_H
|
||||
#define SORTIX_TERMMODE_H
|
||||
|
||||
#define TERMMODE_KBKEY (1U<<0U)
|
||||
#define TERMMODE_UNICODE (1U<<1U)
|
||||
#define TERMMODE_SIGNAL (1U<<2U)
|
||||
#define TERMMODE_UTF8 (1U<<3U)
|
||||
#define TERMMODE_LINEBUFFER (1U<<4U)
|
||||
#define TERMMODE_ECHO (1U<<5U)
|
||||
#define TERMMODE_NONBLOCK (1U<<6U)
|
||||
#define TERMMODE_KBKEY (1U << 0) /* ISORTIX_ENABLE_KBKEY */
|
||||
#define TERMMODE_UNICODE (1U << 1) /* !ISORTIX_DISABLE_CHARS */
|
||||
#define TERMMODE_SIGNAL (1U << 2) /* ISIG */
|
||||
#define TERMMODE_UTF8 (1U << 3) /* !ISORTIX_ENABLE_32BIT */
|
||||
#define TERMMODE_LINEBUFFER (1U << 4) /* ICANON */
|
||||
#define TERMMODE_ECHO (1U << 5) /* ECHO */
|
||||
#define TERMMODE_NONBLOCK (1U << 6) /* ISORTIX_NONBLOCK */
|
||||
#define TERMMODE_TERMIOS (1U << 7) /* !ISORTIX_TERMMODE */
|
||||
#define TERMMODE_DISABLE (1U << 8) /* !CREAD */
|
||||
#define TERMMODE_NORMAL (TERMMODE_UNICODE | TERMMODE_SIGNAL | TERMMODE_UTF8 | \
|
||||
TERMMODE_LINEBUFFER | TERMMODE_ECHO | TERMMODE_TERMIOS)
|
||||
|
||||
#endif
|
||||
|
|
52
kernel/include/sortix/winsize.h
Normal file
52
kernel/include/sortix/winsize.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
sortix/winsize.h
|
||||
Defines values for termios.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef INCLUDE_SORTIX_WINSIZE_H
|
||||
#define INCLUDE_SORTIX_WINSIZE_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sys/__/types.h>
|
||||
|
||||
#ifndef __size_t_defined
|
||||
#define __size_t_defined
|
||||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
struct wincurpos
|
||||
{
|
||||
size_t wcp_row;
|
||||
size_t wcp_col;
|
||||
};
|
||||
|
||||
struct winsize
|
||||
{
|
||||
size_t ws_row;
|
||||
size_t ws_col;
|
||||
size_t ws_xpixel;
|
||||
size_t ws_ypixel;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -412,4 +412,39 @@ int AbstractInode::unmounted(ioctx_t* /*ctx*/)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int AbstractInode::tcdrain(ioctx_t* /*ctx*/)
|
||||
{
|
||||
return errno = ENOTTY, -1;
|
||||
}
|
||||
|
||||
int AbstractInode::tcflow(ioctx_t* /*ctx*/, int /*action*/)
|
||||
{
|
||||
return errno = ENOTTY, -1;
|
||||
}
|
||||
|
||||
int AbstractInode::tcflush(ioctx_t* /*ctx*/, int /*queue_selector*/)
|
||||
{
|
||||
return errno = ENOTTY, -1;
|
||||
}
|
||||
|
||||
int AbstractInode::tcgetattr(ioctx_t* /*ctx*/, struct termios* /*tio*/)
|
||||
{
|
||||
return errno = ENOTTY, -1;
|
||||
}
|
||||
|
||||
pid_t AbstractInode::tcgetsid(ioctx_t* /*ctx*/)
|
||||
{
|
||||
return errno = ENOTTY, -1;
|
||||
}
|
||||
|
||||
int AbstractInode::tcsendbreak(ioctx_t* /*ctx*/, int /*duration*/)
|
||||
{
|
||||
return errno = ENOTTY, -1;
|
||||
}
|
||||
|
||||
int AbstractInode::tcsetattr(ioctx_t* /*ctx*/, int /*actions*/, const struct termios* /*tio*/)
|
||||
{
|
||||
return errno = ENOTTY, -1;
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015, 2016.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <sortix/dirent.h>
|
||||
#include <sortix/fcntl.h>
|
||||
#include <sortix/ioctl.h>
|
||||
#include <sortix/seek.h>
|
||||
#include <sortix/socket.h>
|
||||
#include <sortix/stat.h>
|
||||
|
@ -370,19 +371,15 @@ int sys_fcntl(int fd, int cmd, uintptr_t arg)
|
|||
return errno = EINVAL, -1;
|
||||
}
|
||||
|
||||
int sys_ioctl(int fd, int cmd, void* /*ptr*/)
|
||||
int sys_ioctl(int fd, int cmd, uintptr_t arg)
|
||||
{
|
||||
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
|
||||
if ( !desc )
|
||||
return -1;
|
||||
int ret = -1;
|
||||
switch ( cmd )
|
||||
{
|
||||
case TIOCGWINSZ:
|
||||
return sys_tcgetwinsize(fd, (struct winsize*) arg);
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
return errno = EINVAL, -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t sys_readdirents(int fd, struct kernel_dirent* dirent, size_t size)
|
||||
|
@ -1155,4 +1152,67 @@ int sys_fsm_mountat(int dirfd, const char* path, const struct stat* rootst, int
|
|||
return ret;
|
||||
}
|
||||
|
||||
int sys_tcdrain(int fd)
|
||||
{
|
||||
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
|
||||
if ( !desc )
|
||||
return -1;
|
||||
ioctx_t ctx; SetupUserIOCtx(&ctx);
|
||||
return desc->tcdrain(&ctx);
|
||||
}
|
||||
|
||||
int sys_tcflow(int fd, int action)
|
||||
{
|
||||
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
|
||||
if ( !desc )
|
||||
return -1;
|
||||
ioctx_t ctx; SetupUserIOCtx(&ctx);
|
||||
return desc->tcflow(&ctx, action);
|
||||
}
|
||||
|
||||
int sys_tcflush(int fd, int queue_selector)
|
||||
{
|
||||
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
|
||||
if ( !desc )
|
||||
return -1;
|
||||
ioctx_t ctx; SetupUserIOCtx(&ctx);
|
||||
return desc->tcflush(&ctx, queue_selector);
|
||||
}
|
||||
|
||||
int sys_tcgetattr(int fd, struct termios* tio)
|
||||
{
|
||||
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
|
||||
if ( !desc )
|
||||
return -1;
|
||||
ioctx_t ctx; SetupUserIOCtx(&ctx);
|
||||
return desc->tcgetattr(&ctx, tio);
|
||||
}
|
||||
|
||||
pid_t sys_tcgetsid(int fd)
|
||||
{
|
||||
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
|
||||
if ( !desc )
|
||||
return -1;
|
||||
ioctx_t ctx; SetupUserIOCtx(&ctx);
|
||||
return desc->tcgetsid(&ctx);
|
||||
}
|
||||
|
||||
int sys_tcsendbreak(int fd, int duration)
|
||||
{
|
||||
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
|
||||
if ( !desc )
|
||||
return -1;
|
||||
ioctx_t ctx; SetupUserIOCtx(&ctx);
|
||||
return desc->tcsendbreak(&ctx, duration);
|
||||
}
|
||||
|
||||
int sys_tcsetattr(int fd, int actions, const struct termios* tio)
|
||||
{
|
||||
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
|
||||
if ( !desc )
|
||||
return -1;
|
||||
ioctx_t ctx; SetupUserIOCtx(&ctx);
|
||||
return desc->tcsetattr(&ctx, actions, tio);
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -138,4 +138,12 @@ bool LineBuffer::CanBackspace() const
|
|||
return bufferused - bufferfrozen;
|
||||
}
|
||||
|
||||
void LineBuffer::Flush()
|
||||
{
|
||||
bufferoffset = 0;
|
||||
buffercommitted = 0;
|
||||
bufferfrozen = 0;
|
||||
bufferused = 0;
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
void Freeze();
|
||||
bool CanPop() const;
|
||||
bool CanBackspace() const;
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
uint32_t* buffer;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -25,9 +25,10 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <sortix/fcntl.h>
|
||||
|
@ -37,6 +38,7 @@
|
|||
#include <sortix/stat.h>
|
||||
#include <sortix/termios.h>
|
||||
#include <sortix/termmode.h>
|
||||
#include <sortix/winsize.h>
|
||||
|
||||
#include <sortix/kernel/inode.h>
|
||||
#include <sortix/kernel/interlock.h>
|
||||
|
@ -49,18 +51,86 @@
|
|||
#include <sortix/kernel/ptable.h>
|
||||
#include <sortix/kernel/refcount.h>
|
||||
#include <sortix/kernel/scheduler.h>
|
||||
#include <sortix/kernel/thread.h>
|
||||
|
||||
#include "logterminal.h"
|
||||
|
||||
#define CONTROL(x) (((x) - 64) & 127)
|
||||
#define M_CONTROL(x) (128 + CONTROL(x))
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
const unsigned SUPPORTED_MODES = TERMMODE_KBKEY
|
||||
| TERMMODE_UNICODE
|
||||
| TERMMODE_SIGNAL
|
||||
| TERMMODE_UTF8
|
||||
| TERMMODE_LINEBUFFER
|
||||
| TERMMODE_ECHO
|
||||
| TERMMODE_NONBLOCK;
|
||||
static const unsigned int SUPPORTED_TERMMODES = TERMMODE_KBKEY
|
||||
| TERMMODE_UNICODE
|
||||
| TERMMODE_SIGNAL
|
||||
| TERMMODE_UTF8
|
||||
| TERMMODE_LINEBUFFER
|
||||
| TERMMODE_ECHO
|
||||
| TERMMODE_NONBLOCK
|
||||
| TERMMODE_TERMIOS
|
||||
| TERMMODE_DISABLE;
|
||||
|
||||
static const int MODIFIER_ALT = 1 << 0;
|
||||
static const int MODIFIER_LSHIFT = 1 << 1;
|
||||
static const int MODIFIER_RSHIFT = 1 << 2;
|
||||
static const int MODIFIER_LCONTROL = 1 << 3;
|
||||
static const int MODIFIER_RCONTROL = 1 << 4;
|
||||
|
||||
static const int SEQUENCE_1IFMOD = 1 << 0;
|
||||
static const int SEQUENCE_OSHORT = 1 << 1;
|
||||
|
||||
struct kbkey_sequence
|
||||
{
|
||||
const char* sequence;
|
||||
int kbkey;
|
||||
int flags;
|
||||
};
|
||||
|
||||
static const struct kbkey_sequence kbkey_sequences[] =
|
||||
{
|
||||
{ "\e[A", KBKEY_UP, SEQUENCE_1IFMOD },
|
||||
{ "\e[B", KBKEY_DOWN, SEQUENCE_1IFMOD},
|
||||
{ "\e[C", KBKEY_RIGHT, SEQUENCE_1IFMOD },
|
||||
{ "\e[D", KBKEY_LEFT, SEQUENCE_1IFMOD },
|
||||
{ "\e[F", KBKEY_END, SEQUENCE_1IFMOD },
|
||||
{ "\e[H", KBKEY_HOME, SEQUENCE_1IFMOD },
|
||||
{ "\e[2~", KBKEY_INSERT, 0 },
|
||||
{ "\e[3~", KBKEY_DELETE, 0 },
|
||||
{ "\e[5~", KBKEY_PGUP, 0 },
|
||||
{ "\e[6~", KBKEY_PGDOWN, 0 },
|
||||
{ "\e[1P", KBKEY_F1, SEQUENCE_OSHORT },
|
||||
{ "\e[1Q", KBKEY_F2, SEQUENCE_OSHORT },
|
||||
{ "\e[1R", KBKEY_F3, SEQUENCE_OSHORT },
|
||||
{ "\e[1S", KBKEY_F4, SEQUENCE_OSHORT },
|
||||
{ "\e[15~", KBKEY_F5, 0 },
|
||||
{ "\e[17~", KBKEY_F6, 0 },
|
||||
{ "\e[18~", KBKEY_F7, 0 },
|
||||
{ "\e[19~", KBKEY_F8, 0 },
|
||||
{ "\e[20~", KBKEY_F9, 0 },
|
||||
{ "\e[21~", KBKEY_F10, 0 },
|
||||
{ "\e[23~", KBKEY_F11, 0 },
|
||||
{ "\e[24~", KBKEY_F12, 0 },
|
||||
};
|
||||
|
||||
static inline bool IsByteUnescaped(unsigned char byte)
|
||||
{
|
||||
return (32 <= byte && byte != 127) ||
|
||||
byte == '\t' || byte == '\n' || byte == '\r';
|
||||
}
|
||||
|
||||
static inline bool IsUTF8Continuation(unsigned char byte)
|
||||
{
|
||||
return (byte & 0b11000000) == 0b10000000;
|
||||
}
|
||||
|
||||
static inline const struct kbkey_sequence* LookupKeystrokeSequence(int kbkey)
|
||||
{
|
||||
size_t count = sizeof(kbkey_sequences) / sizeof(kbkey_sequences[0]);
|
||||
for ( size_t i = 0; i < count; i++ )
|
||||
if ( kbkey_sequences[i].kbkey == kbkey )
|
||||
return &kbkey_sequences[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LogTerminal::LogTerminal(dev_t dev, mode_t mode, uid_t owner, gid_t group,
|
||||
Keyboard* keyboard, KeyboardLayoutExecutor* kblayout)
|
||||
|
@ -74,16 +144,28 @@ LogTerminal::LogTerminal(dev_t dev, mode_t mode, uid_t owner, gid_t group,
|
|||
this->stat_gid = group;
|
||||
this->keyboard = keyboard;
|
||||
this->kblayout = kblayout;
|
||||
this->partiallywritten = 0;
|
||||
this->control = false;
|
||||
this->termmode = TERMMODE_UNICODE
|
||||
| TERMMODE_SIGNAL
|
||||
| TERMMODE_UTF8
|
||||
| TERMMODE_LINEBUFFER
|
||||
| TERMMODE_ECHO;
|
||||
this->modifiers = 0;
|
||||
memset(&tio, 0, sizeof(tio));
|
||||
tio.c_iflag = BRKINT | ICRNL | IXANY | IXON;
|
||||
tio.c_oflag = OPOST;
|
||||
tio.c_cflag = CS8 /*| CREAD*/ | HUPCL; // CREAD unset for boot security.
|
||||
tio.c_lflag = ECHO | ECHOE | ECHOK | ICANON | IEXTEN | ISIG;
|
||||
tio.c_cc[VEOF] = CONTROL('D');
|
||||
tio.c_cc[VEOL] = M_CONTROL('?');
|
||||
tio.c_cc[VERASE] = CONTROL('?');
|
||||
tio.c_cc[VINTR] = CONTROL('C');
|
||||
tio.c_cc[VKILL] = CONTROL('U');
|
||||
tio.c_cc[VMIN] = 1;
|
||||
tio.c_cc[VQUIT] = CONTROL('\\');
|
||||
tio.c_cc[VSTART] = CONTROL('Q');
|
||||
tio.c_cc[VSTOP] = CONTROL('S');
|
||||
tio.c_cc[VSUSP] = CONTROL('Z');
|
||||
tio.c_cc[VTIME] = 0;
|
||||
tio.c_cc[VWERASE] = CONTROL('W');
|
||||
tio.c_ispeed = B38400;
|
||||
tio.c_ospeed = B38400;
|
||||
this->termlock = KTHREAD_MUTEX_INITIALIZER;
|
||||
this->datacond = KTHREAD_COND_INITIALIZER;
|
||||
this->numwaiting = 0;
|
||||
this->numeofs = 0;
|
||||
this->foreground_pgid = 0;
|
||||
keyboard->SetOwner(this, NULL);
|
||||
|
@ -95,25 +177,86 @@ LogTerminal::~LogTerminal()
|
|||
delete kblayout;
|
||||
}
|
||||
|
||||
int LogTerminal::settermmode(ioctx_t* /*ctx*/, unsigned newtermmode)
|
||||
int LogTerminal::settermmode(ioctx_t* /*ctx*/, unsigned int termmode)
|
||||
{
|
||||
if ( newtermmode & ~SUPPORTED_MODES ) { errno = EINVAL; return -1; }
|
||||
ScopedLock lock(&termlock);
|
||||
unsigned oldtermmode = termmode;
|
||||
bool oldutf8 = oldtermmode & TERMMODE_UTF8;
|
||||
bool newutf8 = newtermmode & TERMMODE_UTF8;
|
||||
if ( oldutf8 != newutf8 )
|
||||
partiallywritten = 0;
|
||||
termmode = newtermmode;
|
||||
if ( !(newtermmode & TERMMODE_LINEBUFFER) )
|
||||
if ( !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
if ( termmode & ~SUPPORTED_TERMMODES )
|
||||
return errno = EINVAL, -1;
|
||||
tcflag_t old_cflag = tio.c_cflag;
|
||||
tcflag_t new_cflag = old_cflag;
|
||||
tcflag_t old_lflag = tio.c_lflag;
|
||||
tcflag_t new_lflag = old_lflag;
|
||||
if ( termmode & TERMMODE_KBKEY )
|
||||
new_lflag |= ISORTIX_KBKEY;
|
||||
else
|
||||
new_lflag &= ~ISORTIX_KBKEY;
|
||||
if ( !(termmode & TERMMODE_UNICODE) )
|
||||
new_lflag |= ISORTIX_CHARS_DISABLE;
|
||||
else
|
||||
new_lflag &= ~ISORTIX_CHARS_DISABLE;
|
||||
if ( termmode & TERMMODE_SIGNAL )
|
||||
new_lflag |= ISIG;
|
||||
else
|
||||
new_lflag &= ~ISIG;
|
||||
if ( !(termmode & TERMMODE_UTF8) )
|
||||
new_lflag |= ISORTIX_32BIT;
|
||||
else
|
||||
new_lflag &= ~ISORTIX_32BIT;
|
||||
if ( termmode & TERMMODE_LINEBUFFER )
|
||||
new_lflag |= ICANON;
|
||||
else
|
||||
new_lflag &= ~ICANON;
|
||||
if ( termmode & TERMMODE_ECHO )
|
||||
new_lflag |= ECHO | ECHOE;
|
||||
else
|
||||
new_lflag &= ~(ECHO | ECHOE);
|
||||
if ( termmode & TERMMODE_NONBLOCK )
|
||||
new_lflag |= ISORTIX_NONBLOCK;
|
||||
else
|
||||
new_lflag &= ~ISORTIX_NONBLOCK;
|
||||
if ( !(termmode & TERMMODE_TERMIOS) )
|
||||
new_lflag |= ISORTIX_TERMMODE;
|
||||
else
|
||||
new_lflag &= ~ISORTIX_TERMMODE;
|
||||
if ( !(termmode & TERMMODE_DISABLE) )
|
||||
new_cflag |= CREAD;
|
||||
else
|
||||
new_cflag &= ~CREAD;
|
||||
bool oldnoutf8 = old_lflag & ISORTIX_32BIT;
|
||||
bool newnoutf8 = new_lflag & ISORTIX_32BIT;
|
||||
if ( oldnoutf8 != newnoutf8 )
|
||||
memset(&read_ps, 0, sizeof(read_ps));
|
||||
tio.c_cflag = new_cflag;
|
||||
tio.c_lflag = new_lflag;
|
||||
if ( !(tio.c_lflag & ICANON) )
|
||||
CommitLineBuffer();
|
||||
partiallywritten = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LogTerminal::gettermmode(ioctx_t* ctx, unsigned* mode)
|
||||
int LogTerminal::gettermmode(ioctx_t* ctx, unsigned int* mode)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
unsigned int termmode = 0;
|
||||
if ( tio.c_lflag & ISORTIX_KBKEY )
|
||||
termmode |= TERMMODE_KBKEY;
|
||||
if ( !(tio.c_lflag & ISORTIX_CHARS_DISABLE) )
|
||||
termmode |= TERMMODE_UNICODE;
|
||||
if ( tio.c_lflag & ISIG )
|
||||
termmode |= TERMMODE_SIGNAL;
|
||||
if ( !(tio.c_lflag & ISORTIX_32BIT) )
|
||||
termmode |= TERMMODE_UTF8;
|
||||
if ( tio.c_lflag & ICANON )
|
||||
termmode |= TERMMODE_LINEBUFFER;
|
||||
if ( tio.c_lflag & (ECHO | ECHOE) )
|
||||
termmode |= TERMMODE_ECHO;
|
||||
if ( tio.c_lflag & ISORTIX_NONBLOCK )
|
||||
termmode |= TERMMODE_NONBLOCK;
|
||||
if ( !(tio.c_lflag & ISORTIX_TERMMODE) )
|
||||
termmode |= TERMMODE_TERMIOS;
|
||||
if ( !(tio.c_cflag & CREAD) )
|
||||
termmode |= TERMMODE_DISABLE;
|
||||
if ( !ctx->copy_to_dest(mode, &termmode, sizeof(termmode)) )
|
||||
return -1;
|
||||
return 0;
|
||||
|
@ -121,6 +264,7 @@ int LogTerminal::gettermmode(ioctx_t* ctx, unsigned* mode)
|
|||
|
||||
int LogTerminal::tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
struct wincurpos retwcp;
|
||||
memset(&retwcp, 0, sizeof(retwcp));
|
||||
size_t cursor_column, cursor_row;
|
||||
|
@ -134,6 +278,7 @@ int LogTerminal::tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp)
|
|||
|
||||
int LogTerminal::tcgetwinsize(ioctx_t* ctx, struct winsize* ws)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
struct winsize retws;
|
||||
memset(&retws, 0, sizeof(retws));
|
||||
retws.ws_col = Log::Width();
|
||||
|
@ -146,12 +291,16 @@ int LogTerminal::tcgetwinsize(ioctx_t* ctx, struct winsize* ws)
|
|||
int LogTerminal::tcsetpgrp(ioctx_t* /*ctx*/, pid_t pgid)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
Process* process = CurrentProcess()->GetPTable()->Get(pgid);
|
||||
if ( !pgid || !process )
|
||||
if ( !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
if ( pgid <= 0 )
|
||||
return errno = ESRCH, -1;
|
||||
kthread_mutex_lock(&process->groupchildlock);
|
||||
Process* process = CurrentProcess()->GetPTable()->Get(pgid);
|
||||
if ( !process )
|
||||
return errno = ESRCH, -1;
|
||||
kthread_mutex_lock(&process->groupparentlock);
|
||||
bool is_process_group = process->group == process;
|
||||
kthread_mutex_unlock(&process->groupchildlock);
|
||||
kthread_mutex_unlock(&process->groupparentlock);
|
||||
if ( !is_process_group )
|
||||
return errno = EINVAL, -1;
|
||||
foreground_pgid = pgid;
|
||||
|
@ -166,25 +315,160 @@ pid_t LogTerminal::tcgetpgrp(ioctx_t* /*ctx*/)
|
|||
|
||||
int LogTerminal::sync(ioctx_t* /*ctx*/)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
return Log::Sync() ? 0 : -1;
|
||||
}
|
||||
|
||||
void LogTerminal::OnKeystroke(Keyboard* kb, void* /*user*/)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
while ( kb->HasPending() )
|
||||
ProcessKeystroke(kb->Read());
|
||||
{
|
||||
int kbkey = kb->Read();
|
||||
if ( kbkey == KBKEY_LALT )
|
||||
modifiers |= MODIFIER_ALT;
|
||||
else if ( kbkey == -KBKEY_LALT )
|
||||
modifiers &= ~MODIFIER_ALT;
|
||||
else if ( kbkey == KBKEY_LSHIFT )
|
||||
modifiers |= MODIFIER_LSHIFT;
|
||||
else if ( kbkey == -KBKEY_LSHIFT )
|
||||
modifiers &= ~MODIFIER_LSHIFT;
|
||||
else if ( kbkey == KBKEY_RSHIFT )
|
||||
modifiers |= MODIFIER_RSHIFT;
|
||||
else if ( kbkey == -KBKEY_RSHIFT )
|
||||
modifiers &= ~MODIFIER_RSHIFT;
|
||||
else if ( kbkey == KBKEY_LCTRL )
|
||||
modifiers |= MODIFIER_LCONTROL;
|
||||
else if ( kbkey == -KBKEY_LCTRL )
|
||||
modifiers &= ~MODIFIER_LCONTROL;
|
||||
else if ( kbkey == KBKEY_RCTRL )
|
||||
modifiers |= MODIFIER_RCONTROL;
|
||||
else if ( kbkey == -KBKEY_RCTRL )
|
||||
modifiers &= ~MODIFIER_RCONTROL;
|
||||
uint32_t unicode = kblayout->Translate(kbkey);
|
||||
if ( !(tio.c_cflag & CREAD) )
|
||||
continue;
|
||||
ProcessKeystroke(kbkey);
|
||||
if ( !unicode )
|
||||
continue;
|
||||
if ( unicode == '\n' )
|
||||
unicode = '\r';
|
||||
bool control = modifiers & (MODIFIER_LCONTROL | MODIFIER_RCONTROL);
|
||||
if ( !(tio.c_cflag & ISORTIX_TERMMODE) && unicode == '\b' )
|
||||
unicode = 127;
|
||||
if ( control && unicode == L' ' )
|
||||
ProcessByte(0, unicode);
|
||||
else if ( control && (L'`' <= unicode && unicode <= L'}') )
|
||||
ProcessByte(unicode - L'`', unicode);
|
||||
else if ( control && (L'@' <= unicode && unicode <= L'_') )
|
||||
ProcessByte(unicode - L'@', unicode);
|
||||
else if ( control && unicode == L'?' )
|
||||
ProcessByte(127, unicode);
|
||||
else
|
||||
ProcessUnicode(unicode);
|
||||
}
|
||||
}
|
||||
|
||||
void LogTerminal::ProcessKeystroke(int kbkey)
|
||||
{
|
||||
if ( !kbkey )
|
||||
if ( tio.c_lflag & ISORTIX_32BIT )
|
||||
{
|
||||
if ( tio.c_lflag & ISORTIX_KBKEY )
|
||||
{
|
||||
uint32_t unikbkey = KBKEY_ENCODE(kbkey);
|
||||
if ( !linebuffer.Push(unikbkey) )
|
||||
return;
|
||||
if ( !(tio.c_lflag & ICANON) )
|
||||
CommitLineBuffer();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( kbkey < 0 )
|
||||
return;
|
||||
|
||||
ScopedLock lock(&termlock);
|
||||
const struct kbkey_sequence* seq = LookupKeystrokeSequence(kbkey);
|
||||
if ( !seq )
|
||||
return;
|
||||
|
||||
if ( kbkey == KBKEY_LCTRL ) { control = true; }
|
||||
if ( kbkey == -KBKEY_LCTRL ) { control = false; }
|
||||
if ( termmode & TERMMODE_SIGNAL && control && kbkey == KBKEY_C )
|
||||
const char* str = seq->sequence;
|
||||
size_t len = strlen(str);
|
||||
|
||||
int mods = 0;
|
||||
if ( modifiers & (MODIFIER_LSHIFT | MODIFIER_RSHIFT) )
|
||||
mods |= 1;
|
||||
if ( modifiers & MODIFIER_ALT )
|
||||
mods |= 2;
|
||||
if ( modifiers & (MODIFIER_LCONTROL | MODIFIER_RCONTROL) )
|
||||
mods |= 4;
|
||||
|
||||
if ( (seq->flags & SEQUENCE_OSHORT) && mods == 0 )
|
||||
{
|
||||
ProcessByte('\e');
|
||||
ProcessByte('O');
|
||||
ProcessByte((unsigned char) str[len-1]);
|
||||
return;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < len - 1; i++ )
|
||||
ProcessByte((unsigned char) str[i]);
|
||||
if ( seq->flags & SEQUENCE_1IFMOD && mods != 0 )
|
||||
ProcessByte('1');
|
||||
if ( mods )
|
||||
{
|
||||
ProcessByte(';');
|
||||
ProcessByte('1' + mods);
|
||||
}
|
||||
ProcessByte(str[len-1]);
|
||||
}
|
||||
|
||||
void LogTerminal::ProcessString(const char* string)
|
||||
{
|
||||
for ( size_t i = 0; string[i]; i++ )
|
||||
ProcessByte((unsigned char) string[i]);
|
||||
}
|
||||
|
||||
void LogTerminal::ProcessUnicode(uint32_t unicode)
|
||||
{
|
||||
mbstate_t ps;
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
char mb[MB_CUR_MAX];
|
||||
size_t amount = wcrtomb(mb, unicode, &ps);
|
||||
for ( size_t i = 0; amount != (size_t) -1 && i < amount; i++ )
|
||||
ProcessByte((unsigned char) mb[i]);
|
||||
}
|
||||
|
||||
bool LogTerminal::CheckHandledByte(tcflag_t lflags,
|
||||
unsigned char key,
|
||||
unsigned char byte)
|
||||
{
|
||||
return (tio.c_lflag & lflags) == lflags && key && key == byte;
|
||||
}
|
||||
|
||||
void LogTerminal::ProcessByte(unsigned char byte, uint32_t control_unicode)
|
||||
{
|
||||
if ( byte == '\r' && tio.c_iflag & IGNCR )
|
||||
return;
|
||||
if ( byte == '\r' && tio.c_iflag & ICRNL )
|
||||
byte = '\n';
|
||||
else if ( byte == '\n' && tio.c_iflag & INLCR )
|
||||
byte = '\r';
|
||||
|
||||
// TODO: tio.c_cc[VEOL]
|
||||
// TODO: tio.c_cc[VSTART]
|
||||
// TODO: tio.c_cc[VSTOP]
|
||||
// TODO: tio.c_cc[VSUSP]
|
||||
|
||||
if ( CheckHandledByte(ISIG, tio.c_cc[VQUIT], byte) )
|
||||
{
|
||||
while ( linebuffer.CanBackspace() )
|
||||
linebuffer.Backspace();
|
||||
if ( Process* process = CurrentProcess()->GetPTable()->Get(foreground_pgid) )
|
||||
process->DeliverGroupSignal(SIGQUIT);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( CheckHandledByte(ISIG, tio.c_cc[VINTR], byte) )
|
||||
{
|
||||
while ( linebuffer.CanBackspace() )
|
||||
linebuffer.Backspace();
|
||||
|
@ -192,236 +476,250 @@ void LogTerminal::ProcessKeystroke(int kbkey)
|
|||
process->DeliverGroupSignal(SIGINT);
|
||||
return;
|
||||
}
|
||||
if ( termmode & TERMMODE_SIGNAL && control && kbkey == KBKEY_D )
|
||||
|
||||
if ( CheckHandledByte(ISIG | ICANON, tio.c_cc[VEOF], byte) )
|
||||
{
|
||||
if ( !linebuffer.CanPop() )
|
||||
{
|
||||
numeofs++;
|
||||
if ( numwaiting )
|
||||
kthread_cond_broadcast(&datacond);
|
||||
kthread_cond_broadcast(&datacond);
|
||||
poll_channel.Signal(POLLIN | POLLRDNORM);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( termmode & TERMMODE_LINEBUFFER && control && kbkey == KBKEY_W )
|
||||
if ( CheckHandledByte(ISIG, tio.c_cc[VQUIT], byte) )
|
||||
{
|
||||
bool had_non_whitespace = false;
|
||||
c_w_delete_more:
|
||||
if ( !linebuffer.CanBackspace() ) { return; }
|
||||
uint32_t delchar = linebuffer.WouldBackspace();
|
||||
bool waskbkey = KBKEY_DECODE(delchar);
|
||||
bool wasuni = !waskbkey;
|
||||
bool whitespace =
|
||||
(wasuni && (delchar == ' ' ||
|
||||
delchar == '\t' ||
|
||||
delchar == '\n')) ||
|
||||
(waskbkey && (abs(KBKEY_DECODE(delchar)) == -KBKEY_SPACE ||
|
||||
abs(KBKEY_DECODE(delchar)) == -KBKEY_TAB ||
|
||||
abs(KBKEY_DECODE(delchar)) == -KBKEY_ENTER));
|
||||
if ( wasuni && whitespace && had_non_whitespace )
|
||||
return;
|
||||
if ( wasuni && !whitespace )
|
||||
had_non_whitespace = true;
|
||||
linebuffer.Backspace();
|
||||
if ( (!waskbkey || termmode & TERMMODE_KBKEY) &&
|
||||
(!wasuni || termmode & TERMMODE_UNICODE) &&
|
||||
termmode & TERMMODE_ECHO &&
|
||||
wasuni )
|
||||
Log::Print("\b \b");
|
||||
goto c_w_delete_more;
|
||||
while ( linebuffer.CanBackspace() )
|
||||
linebuffer.Backspace();
|
||||
if ( Process* process = CurrentProcess()->GetPTable()->Get(foreground_pgid) )
|
||||
process->DeliverGroupSignal(SIGQUIT);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( termmode & TERMMODE_LINEBUFFER && control && kbkey == KBKEY_U )
|
||||
if ( CheckHandledByte(ICANON, tio.c_cc[VERASE], byte) ||
|
||||
CheckHandledByte(ICANON | ISORTIX_TERMMODE, '\b', byte) )
|
||||
{
|
||||
while ( linebuffer.CanBackspace() )
|
||||
{
|
||||
uint32_t delchar = linebuffer.Backspace();
|
||||
bool waskbkey = KBKEY_DECODE(delchar);
|
||||
bool wasuni = !waskbkey;
|
||||
if ( (!waskbkey || termmode & TERMMODE_KBKEY) &&
|
||||
(!wasuni || termmode & TERMMODE_UNICODE) &&
|
||||
termmode & TERMMODE_ECHO &&
|
||||
wasuni )
|
||||
if ( 256 <= delchar )
|
||||
continue;
|
||||
if ( IsUTF8Continuation(delchar) )
|
||||
continue;
|
||||
if ( tio.c_lflag & ECHOE )
|
||||
{
|
||||
// TODO: Handle tab specially. (Is that even possible without
|
||||
// knowing cursor position?).
|
||||
Log::Print("\b \b");
|
||||
if ( !IsByteUnescaped(delchar) )
|
||||
Log::Print("\b \b");
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( termmode & TERMMODE_LINEBUFFER && control && kbkey == KBKEY_L )
|
||||
if ( CheckHandledByte(ICANON, tio.c_cc[VWERASE], byte) )
|
||||
{
|
||||
bool had_non_whitespace = false;
|
||||
while ( linebuffer.CanBackspace() )
|
||||
{
|
||||
uint32_t delchar = linebuffer.WouldBackspace();
|
||||
if ( 256 <= delchar )
|
||||
continue;
|
||||
if ( IsUTF8Continuation(delchar) )
|
||||
continue;
|
||||
if ( delchar == L' ' || delchar == L'\t' || delchar == L'\n' )
|
||||
{
|
||||
if ( had_non_whitespace )
|
||||
break;
|
||||
}
|
||||
else
|
||||
had_non_whitespace = true;
|
||||
linebuffer.Backspace();
|
||||
if ( tio.c_lflag & ECHOE )
|
||||
{
|
||||
Log::Print("\b \b");
|
||||
if ( !IsByteUnescaped(delchar) )
|
||||
Log::Print("\b \b");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( CheckHandledByte(ICANON, tio.c_cc[VKILL], byte) )
|
||||
{
|
||||
while ( linebuffer.CanBackspace() )
|
||||
{
|
||||
uint32_t delchar = linebuffer.Backspace();
|
||||
if ( 256 <= delchar )
|
||||
continue;
|
||||
if ( IsUTF8Continuation(delchar) )
|
||||
continue;
|
||||
if ( tio.c_lflag & ECHOE )
|
||||
{
|
||||
Log::Print("\b \b");
|
||||
if ( !IsByteUnescaped(delchar) )
|
||||
Log::Print("\b \b");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( CheckHandledByte(ICANON | ISORTIX_TERMMODE, CONTROL('L'), byte) )
|
||||
{
|
||||
while ( linebuffer.CanBackspace() )
|
||||
linebuffer.Backspace();
|
||||
QueueUnicode(KBKEY_ENCODE(KBKEY_ENTER));
|
||||
QueueUnicode('\n');
|
||||
QueueUnicode(KBKEY_ENCODE(-KBKEY_ENTER));
|
||||
ProcessUnicode(KBKEY_ENCODE(KBKEY_ENTER));
|
||||
ProcessByte('\n');
|
||||
ProcessUnicode(KBKEY_ENCODE(-KBKEY_ENTER));
|
||||
Log::PrintF("\e[H\e[2J");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t unikbkey = KBKEY_ENCODE(kbkey);
|
||||
QueueUnicode(unikbkey);
|
||||
uint32_t unicode = kblayout->Translate(kbkey);
|
||||
if ( 0 < kbkey )
|
||||
QueueUnicode(unicode);
|
||||
}
|
||||
|
||||
void LogTerminal::QueueUnicode(uint32_t unicode)
|
||||
{
|
||||
if ( !unicode )
|
||||
if ( tio.c_lflag & ISORTIX_CHARS_DISABLE )
|
||||
return;
|
||||
|
||||
int kbkey = KBKEY_DECODE(unicode);
|
||||
int abskbkey = (kbkey < 0) ? -kbkey : kbkey;
|
||||
bool wasenter = kbkey == KBKEY_ENTER || unicode == '\n';
|
||||
bool kbkeymode = termmode & TERMMODE_KBKEY;
|
||||
bool unicodemode = termmode & TERMMODE_UNICODE;
|
||||
bool linemode = termmode & TERMMODE_LINEBUFFER;
|
||||
bool echomode = termmode & TERMMODE_ECHO;
|
||||
|
||||
if ( linemode && abskbkey == KBKEY_BKSPC ) { return; }
|
||||
while ( linemode && unicode == '\b' )
|
||||
if ( control_unicode &&
|
||||
!(tio.c_lflag & (ICANON | ISIG)) &&
|
||||
tio.c_lflag & ISORTIX_KBKEY )
|
||||
{
|
||||
if ( !linebuffer.CanBackspace() ) { return; }
|
||||
uint32_t delchar = linebuffer.Backspace();
|
||||
bool waskbkey = KBKEY_DECODE(delchar);
|
||||
bool wasuni = !waskbkey;
|
||||
if ( waskbkey && !kbkeymode ) { continue; }
|
||||
if ( wasuni && !unicodemode ) { continue; }
|
||||
if ( !echomode ) { return; }
|
||||
if ( wasuni ) { Log::Print("\b \b"); }
|
||||
ProcessUnicode(control_unicode);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !linebuffer.Push(unicode) )
|
||||
{
|
||||
Log::PrintF("Warning: LogTerminal driver dropping keystroke due "
|
||||
"to insufficient buffer space\n");
|
||||
if ( !linebuffer.Push(byte) )
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Could it be the right thing to print the unicode character even
|
||||
// if it is unprintable (it's an encoded keystroke)?
|
||||
if ( !KBKEY_DECODE(unicode) && echomode )
|
||||
if ( tio.c_lflag & ECHO )
|
||||
{
|
||||
mbstate_t ps;
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
char utf8buf[MB_CUR_MAX];
|
||||
size_t num_bytes = wcrtomb(utf8buf, (wchar_t) unicode, &ps);
|
||||
if ( num_bytes == 1 && utf8buf[0] == '\b' )
|
||||
Log::PrintData("\b \b", 3);
|
||||
if ( IsByteUnescaped(byte) )
|
||||
Log::PrintData(&byte, 1);
|
||||
else
|
||||
Log::PrintData(utf8buf, num_bytes);
|
||||
Log::PrintF("^%c", CONTROL(byte));
|
||||
}
|
||||
|
||||
bool commit = !linemode || wasenter;
|
||||
if ( commit )
|
||||
if ( !(tio.c_lflag & ICANON) || byte == '\n' )
|
||||
CommitLineBuffer();
|
||||
}
|
||||
|
||||
void LogTerminal::CommitLineBuffer()
|
||||
{
|
||||
linebuffer.Commit();
|
||||
if ( numwaiting )
|
||||
if ( linebuffer.CanPop() || numeofs )
|
||||
{
|
||||
kthread_cond_broadcast(&datacond);
|
||||
poll_channel.Signal(POLLIN | POLLRDNORM);
|
||||
poll_channel.Signal(POLLIN | POLLRDNORM);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t LogTerminal::read(ioctx_t* ctx, uint8_t* userbuf, size_t count)
|
||||
{
|
||||
ScopedLockSignal lock(&termlock);
|
||||
if ( !lock.IsAcquired() ) { errno = EINTR; return -1; }
|
||||
if ( !lock.IsAcquired() )
|
||||
return errno = EINTR, -1;
|
||||
if ( !RequireForeground(SIGTTIN) )
|
||||
return errno = EINTR, -1;
|
||||
size_t sofar = 0;
|
||||
size_t left = count;
|
||||
bool blocking = !(termmode & TERMMODE_NONBLOCK);
|
||||
while ( left && !linebuffer.CanPop() && blocking && !numeofs )
|
||||
{
|
||||
if ( ctx->dflags & O_NONBLOCK )
|
||||
return errno = EWOULDBLOCK, -1;
|
||||
numwaiting++;
|
||||
bool abort = !kthread_cond_wait_signal(&datacond, &termlock);
|
||||
numwaiting--;
|
||||
if ( abort ) { errno = EINTR; return -1; }
|
||||
}
|
||||
if ( left && !linebuffer.CanPop() && !blocking && !numeofs )
|
||||
{
|
||||
errno = EWOULDBLOCK;
|
||||
return -1;
|
||||
}
|
||||
if ( numeofs )
|
||||
{
|
||||
numeofs--;
|
||||
return 0;
|
||||
}
|
||||
while ( left && linebuffer.CanPop() )
|
||||
bool nonblocking = tio.c_lflag & ISORTIX_NONBLOCK ||
|
||||
ctx->dflags & O_NONBLOCK;
|
||||
while ( left )
|
||||
{
|
||||
while ( !(linebuffer.CanPop() || numeofs) )
|
||||
{
|
||||
if ( sofar )
|
||||
return sofar;
|
||||
if ( nonblocking )
|
||||
return errno = EWOULDBLOCK, -1;
|
||||
if ( !kthread_cond_wait_signal(&datacond, &termlock) )
|
||||
return errno = EINTR, -1;
|
||||
if ( !RequireForeground(SIGTTIN) )
|
||||
return errno = EINTR, -1;
|
||||
}
|
||||
if ( numeofs )
|
||||
{
|
||||
if ( sofar )
|
||||
return sofar;
|
||||
return numeofs--, 0;
|
||||
}
|
||||
uint32_t codepoint = linebuffer.Peek();
|
||||
int kbkey = KBKEY_DECODE(codepoint);
|
||||
|
||||
bool ignore = false;
|
||||
if ( !(termmode & TERMMODE_KBKEY) && kbkey ) { ignore = true; }
|
||||
if ( !(termmode & TERMMODE_UNICODE) && !kbkey ) { ignore = true; }
|
||||
if ( ignore ) { linebuffer.Pop(); continue; }
|
||||
|
||||
uint8_t* buf;
|
||||
size_t bufsize;
|
||||
uint8_t codepointbuf[4];
|
||||
char utf8buf[MB_CUR_MAX];
|
||||
|
||||
if ( termmode & TERMMODE_UTF8 )
|
||||
if ( tio.c_lflag & ISORTIX_32BIT )
|
||||
{
|
||||
mbstate_t ps;
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
size_t num_bytes = wcrtomb(utf8buf, (wchar_t) codepoint, &ps);
|
||||
if ( num_bytes == (size_t) -1)
|
||||
if ( left < sizeof(codepoint) )
|
||||
return sofar;
|
||||
linebuffer.Pop();
|
||||
if ( 256 <= codepoint && !(tio.c_lflag & ISORTIX_KBKEY) )
|
||||
continue;
|
||||
if ( codepoint < 256 && tio.c_lflag & ISORTIX_CHARS_DISABLE )
|
||||
continue;
|
||||
if ( codepoint < 256 )
|
||||
{
|
||||
Log::PrintF("Warning: logterminal driver dropping invalid "
|
||||
"codepoint 0x%x\n", codepoint);
|
||||
num_bytes = 0;
|
||||
char c = codepoint;
|
||||
wchar_t wc;
|
||||
size_t amount = mbrtowc(&wc, &c, 1, &read_ps);
|
||||
if ( amount == (size_t) -2 )
|
||||
continue;
|
||||
if ( amount == (size_t) -1 )
|
||||
{
|
||||
memset(&read_ps, 0, sizeof(read_ps));
|
||||
wc = 0xFFFD; /* REPLACEMENT CHARACTER */
|
||||
}
|
||||
codepoint = wc;
|
||||
}
|
||||
buf = (uint8_t*) utf8buf;
|
||||
bufsize = num_bytes;
|
||||
if ( !ctx->copy_to_dest(userbuf + sofar, &codepoint,
|
||||
sizeof(codepoint)) )
|
||||
return sofar ? sofar : -1;
|
||||
left -= sizeof(codepoint);
|
||||
sofar += sizeof(codepoint);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if ( 256 <= codepoint )
|
||||
{
|
||||
codepointbuf[0] = (codepoint >> 24U) & 0xFFU;
|
||||
codepointbuf[1] = (codepoint >> 16U) & 0xFFU;
|
||||
codepointbuf[2] = (codepoint >> 8U) & 0xFFU;
|
||||
codepointbuf[3] = (codepoint >> 0U) & 0xFFU;
|
||||
buf = (uint8_t*) &codepointbuf;
|
||||
bufsize = sizeof(codepointbuf);
|
||||
// TODO: Whoops, the above is big-endian and the user programs
|
||||
// expect the data to be in the host endian. That's bad. For now
|
||||
// just send the data in host endian, but this will break when
|
||||
// terminals are accessed over the network.
|
||||
buf = (uint8_t*) &codepoint;
|
||||
linebuffer.Pop();
|
||||
continue;
|
||||
}
|
||||
if ( bufsize < partiallywritten ) { partiallywritten = bufsize; }
|
||||
buf += partiallywritten;
|
||||
bufsize -= partiallywritten;
|
||||
if ( sofar && left < bufsize ) { return sofar; }
|
||||
size_t amount = left < bufsize ? left : bufsize;
|
||||
ctx->copy_to_dest(userbuf + sofar, buf, amount);
|
||||
partiallywritten = (amount < bufsize) ? partiallywritten + amount : 0;
|
||||
left -= amount;
|
||||
sofar += amount;
|
||||
if ( !partiallywritten ) { linebuffer.Pop(); }
|
||||
unsigned char c = codepoint;
|
||||
if ( !ctx->copy_to_dest(userbuf + sofar, &c, 1) )
|
||||
return sofar ? sofar : -1;
|
||||
linebuffer.Pop();
|
||||
left -= 1;
|
||||
sofar += 1;
|
||||
if ( tio.c_lflag & ICANON && c == '\n' )
|
||||
break;
|
||||
}
|
||||
|
||||
return sofar;
|
||||
}
|
||||
|
||||
ssize_t LogTerminal::write(ioctx_t* ctx, const uint8_t* io_buffer, size_t count)
|
||||
{
|
||||
ScopedLockSignal lock(&termlock);
|
||||
if ( tio.c_lflag & TOSTOP && !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
// TODO: Add support for ioctx to the kernel log.
|
||||
const size_t BUFFER_SIZE = 64UL;
|
||||
if ( BUFFER_SIZE < count )
|
||||
count = BUFFER_SIZE;
|
||||
char buffer[BUFFER_SIZE];
|
||||
if ( !ctx->copy_from_src(buffer, io_buffer, count) )
|
||||
return -1;
|
||||
Log::PrintData(buffer, count);
|
||||
return count;
|
||||
size_t sofar = 0;
|
||||
while ( sofar < count )
|
||||
{
|
||||
size_t amount = count - sofar;
|
||||
if ( BUFFER_SIZE < amount )
|
||||
amount = BUFFER_SIZE;
|
||||
if ( !ctx->copy_from_src(buffer, io_buffer + sofar, amount) )
|
||||
return -1;
|
||||
Log::PrintData(buffer, amount);
|
||||
sofar += amount;
|
||||
if ( sofar < count )
|
||||
{
|
||||
kthread_mutex_unlock(&termlock);
|
||||
kthread_yield();
|
||||
kthread_mutex_lock(&termlock);
|
||||
if ( Signal::IsPending() )
|
||||
return sofar;
|
||||
}
|
||||
}
|
||||
return (ssize_t) sofar;
|
||||
}
|
||||
|
||||
short LogTerminal::PollEventStatus()
|
||||
|
@ -496,4 +794,99 @@ ssize_t LogTerminal::tcsetblob(ioctx_t* ctx, const char* name, const void* buffe
|
|||
else
|
||||
return errno = ENOENT, -1;
|
||||
}
|
||||
|
||||
int LogTerminal::tcdrain(ioctx_t* /*ctx*/)
|
||||
{
|
||||
ScopedLockSignal lock(&termlock);
|
||||
if ( !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LogTerminal::tcflow(ioctx_t* /*ctx*/, int action)
|
||||
{
|
||||
ScopedLockSignal lock(&termlock);
|
||||
if ( !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
switch ( action )
|
||||
{
|
||||
case TCOOFF: break; // TODO: Suspend output.
|
||||
case TCOON: break; // TODO: Resume suspended output.
|
||||
case TCIOFF: break; // TODO: Transmit STOP character.
|
||||
case TCION: break; // TODO: Transmit START character.
|
||||
default: return errno = EINVAL -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LogTerminal::tcflush(ioctx_t* /*ctx*/, int queue_selector)
|
||||
{
|
||||
if ( queue_selector & ~TCIOFLUSH )
|
||||
return errno = EINVAL, -1;
|
||||
ScopedLockSignal lock(&termlock);
|
||||
if ( !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
if ( queue_selector & TCIFLUSH )
|
||||
linebuffer.Flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LogTerminal::tcgetattr(ioctx_t* ctx, struct termios* io_tio)
|
||||
{
|
||||
ScopedLockSignal lock(&termlock);
|
||||
if ( !ctx->copy_to_dest(io_tio, &tio, sizeof(tio)) )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid_t LogTerminal::tcgetsid(ioctx_t* /*ctx*/)
|
||||
{
|
||||
// TODO: Implement sessions.
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LogTerminal::tcsendbreak(ioctx_t* /*ctx*/, int /*duration*/)
|
||||
{
|
||||
ScopedLockSignal lock(&termlock);
|
||||
if ( !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LogTerminal::tcsetattr(ioctx_t* ctx, int actions, const struct termios* io_tio)
|
||||
{
|
||||
ScopedLockSignal lock(&termlock);
|
||||
if ( !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
switch ( actions )
|
||||
{
|
||||
case TCSANOW: break;
|
||||
case TCSADRAIN: break;
|
||||
case TCSAFLUSH: linebuffer.Flush(); break;
|
||||
default: return errno = EINVAL, -1;
|
||||
}
|
||||
if ( !ctx->copy_from_src(&tio, io_tio, sizeof(tio)) )
|
||||
return -1;
|
||||
// TODO: Potentially take action here if something changed.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LogTerminal::RequireForeground(int sig)
|
||||
{
|
||||
Thread* thread = CurrentThread();
|
||||
Process* process = thread->process;
|
||||
ScopedLock group_lock(&process->groupparentlock);
|
||||
if ( process->group->pid == foreground_pgid )
|
||||
return true;
|
||||
if ( sigismember(&thread->signal_mask, sig) )
|
||||
return true;
|
||||
ScopedLock signal_lock(&process->signal_lock);
|
||||
if ( process->signal_actions[sig].sa_handler == SIG_IGN )
|
||||
return true;
|
||||
signal_lock.Reset();
|
||||
group_lock.Reset();
|
||||
process->group->DeliverGroupSignal(sig);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2014, 2015, 2016.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -25,6 +25,10 @@
|
|||
#ifndef SORTIX_LOGTERMINAL_H
|
||||
#define SORTIX_LOGTERMINAL_H
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include <sortix/termios.h>
|
||||
|
||||
#include <sortix/kernel/kthread.h>
|
||||
#include <sortix/kernel/inode.h>
|
||||
#include <sortix/kernel/keyboard.h>
|
||||
|
@ -56,30 +60,40 @@ public:
|
|||
virtual int poll(ioctx_t* ctx, PollNode* node);
|
||||
virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count);
|
||||
virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count);
|
||||
|
||||
virtual int tcdrain(ioctx_t* ctx);
|
||||
virtual int tcflow(ioctx_t* ctx, int action);
|
||||
virtual int tcflush(ioctx_t* ctx, int queue_selector);
|
||||
virtual int tcgetattr(ioctx_t* ctx, struct termios* tio);
|
||||
virtual pid_t tcgetsid(ioctx_t* ctx);
|
||||
virtual int tcsendbreak(ioctx_t* ctx, int duration);
|
||||
virtual int tcsetattr(ioctx_t* ctx, int actions, const struct termios* tio);
|
||||
|
||||
public:
|
||||
virtual void OnKeystroke(Keyboard* keyboard, void* user);
|
||||
|
||||
private:
|
||||
void ProcessKeystroke(int kbkey);
|
||||
void QueueUnicode(uint32_t unicode);
|
||||
void ProcessString(const char* string);
|
||||
void ProcessUnicode(uint32_t unicode);
|
||||
void ProcessByte(unsigned char byte, uint32_t control_unicode = 0);
|
||||
void CommitLineBuffer();
|
||||
short PollEventStatus();
|
||||
bool CheckForeground();
|
||||
bool RequireForeground(int sig);
|
||||
bool CheckHandledByte(tcflag_t lflags, unsigned char key, unsigned char byte);
|
||||
|
||||
private:
|
||||
PollChannel poll_channel;
|
||||
mutable kthread_mutex_t termlock;
|
||||
kthread_cond_t datacond;
|
||||
size_t numwaiting;
|
||||
mbstate_t read_ps;
|
||||
size_t numeofs;
|
||||
Keyboard* keyboard;
|
||||
KeyboardLayoutExecutor* kblayout;
|
||||
LineBuffer linebuffer;
|
||||
size_t partiallywritten;
|
||||
unsigned termmode;
|
||||
struct termios tio;
|
||||
pid_t foreground_pgid;
|
||||
bool control;
|
||||
int modifiers;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -190,13 +190,13 @@ void* syscall_list[SYSCALL_MAX_NUM + 1] =
|
|||
[SYSCALL_CLOSEFROM] = (void*) sys_closefrom,
|
||||
[SYSCALL_RESERVED1] = (void*) sys_bad_syscall,
|
||||
[SYSCALL_PSCTL] = (void*) sys_psctl,
|
||||
[SYSCALL_RESERVED2] = (void*) sys_bad_syscall,
|
||||
[SYSCALL_RESERVED3] = (void*) sys_bad_syscall,
|
||||
[SYSCALL_RESERVED4] = (void*) sys_bad_syscall,
|
||||
[SYSCALL_RESERVED5] = (void*) sys_bad_syscall,
|
||||
[SYSCALL_RESERVED6] = (void*) sys_bad_syscall,
|
||||
[SYSCALL_RESERVED7] = (void*) sys_bad_syscall,
|
||||
[SYSCALL_RESERVED8] = (void*) sys_bad_syscall,
|
||||
[SYSCALL_TCDRAIN] = (void*) sys_tcdrain,
|
||||
[SYSCALL_TCFLOW] = (void*) sys_tcflow,
|
||||
[SYSCALL_TCFLUSH] = (void*) sys_tcflush,
|
||||
[SYSCALL_TCGETATTR] = (void*) sys_tcgetattr,
|
||||
[SYSCALL_TCGETSID] = (void*) sys_tcgetsid,
|
||||
[SYSCALL_TCSENDBREAK] = (void*) sys_tcsendbreak,
|
||||
[SYSCALL_TCSETATTR] = (void*) sys_tcsetattr,
|
||||
[SYSCALL_SCRAM] = (void*) sys_scram,
|
||||
[SYSCALL_MAX_NUM] = (void*) sys_bad_syscall,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -424,4 +424,39 @@ ssize_t Vnode::tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, siz
|
|||
return inode->tcsetblob(ctx, name, buffer, count);
|
||||
}
|
||||
|
||||
int Vnode::tcdrain(ioctx_t* ctx)
|
||||
{
|
||||
return inode->tcdrain(ctx);
|
||||
}
|
||||
|
||||
int Vnode::tcflow(ioctx_t* ctx, int action)
|
||||
{
|
||||
return inode->tcflow(ctx, action);
|
||||
}
|
||||
|
||||
int Vnode::tcflush(ioctx_t* ctx, int queue_selector)
|
||||
{
|
||||
return inode->tcflush(ctx, queue_selector);
|
||||
}
|
||||
|
||||
int Vnode::tcgetattr(ioctx_t* ctx, struct termios* tio)
|
||||
{
|
||||
return inode->tcgetattr(ctx, tio);
|
||||
}
|
||||
|
||||
pid_t Vnode::tcgetsid(ioctx_t* ctx)
|
||||
{
|
||||
return inode->tcgetsid(ctx);
|
||||
}
|
||||
|
||||
int Vnode::tcsendbreak(ioctx_t* ctx, int duration)
|
||||
{
|
||||
return inode->tcsendbreak(ctx, duration);
|
||||
}
|
||||
|
||||
int Vnode::tcsetattr(ioctx_t* ctx, int actions, const struct termios* tio)
|
||||
{
|
||||
return inode->tcsetattr(ctx, actions, tio);
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -241,6 +241,10 @@ string/strverscmp.o \
|
|||
string/strxfrm_l.o \
|
||||
string/strxfrm.o \
|
||||
string/timingsafe_memcmp.o \
|
||||
termios/cfgetispeed.o \
|
||||
termios/cfgetospeed.o \
|
||||
termios/cfsetispeed.o \
|
||||
termios/cfsetospeed.o \
|
||||
time/asctime.o \
|
||||
time/asctime_r.o \
|
||||
time/gmtime.o \
|
||||
|
@ -544,9 +548,16 @@ sys/uio/writev.o \
|
|||
sys/utsname/uname.o \
|
||||
sys/wait/wait.o \
|
||||
sys/wait/waitpid.o \
|
||||
termios/tcdrain.o \
|
||||
termios/tcflow.o \
|
||||
termios/tcflush.o \
|
||||
termios/tcgetattr.o \
|
||||
termios/tcgetblob.o \
|
||||
termios/tcgetsid.o \
|
||||
termios/tcgetwincurpos.o \
|
||||
termios/tcgetwinsize.o \
|
||||
termios/tcsendbreak.o \
|
||||
termios/tcsetattr.o \
|
||||
termios/tcsetblob.o \
|
||||
time/clock_getres.o \
|
||||
time/clock_gettime.o \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
|||
#include <sortix/statvfs.h>
|
||||
#include <sortix/termios.h>
|
||||
#include <sortix/timespec.h>
|
||||
#include <sortix/winsize.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -434,8 +435,66 @@ struct fsm_resp_tcgetwincurpos
|
|||
struct wincurpos pos;
|
||||
};
|
||||
|
||||
#define FSM_REQ_TCDRAIN 54
|
||||
struct fsm_req_tcdrain
|
||||
{
|
||||
ino_t ino;
|
||||
};
|
||||
|
||||
#define FSM_MSG_NUM 53
|
||||
#define FSM_REQ_TCFLOW 55
|
||||
struct fsm_req_tcflow
|
||||
{
|
||||
ino_t ino;
|
||||
int action;
|
||||
};
|
||||
|
||||
#define FSM_REQ_TCFLUSH 56
|
||||
struct fsm_req_tcflush
|
||||
{
|
||||
ino_t ino;
|
||||
int queue_selector;
|
||||
};
|
||||
|
||||
#define FSM_REQ_TCGETATTR 57
|
||||
struct fsm_req_tcgetattr
|
||||
{
|
||||
ino_t ino;
|
||||
};
|
||||
|
||||
#define FSM_RESP_TCGETATTR 58
|
||||
struct fsm_resp_tcgetattr
|
||||
{
|
||||
struct termios tio;
|
||||
};
|
||||
|
||||
#define FSM_REQ_TCGETSID 59
|
||||
struct fsm_req_tcgetsid
|
||||
{
|
||||
ino_t ino;
|
||||
};
|
||||
|
||||
#define FSM_RESP_TCGETSID 60
|
||||
struct fsm_resp_tcgetsid
|
||||
{
|
||||
pid_t sid;
|
||||
};
|
||||
|
||||
#define FSM_REQ_TCSENDBREAK 61
|
||||
struct fsm_req_tcsendbreak
|
||||
{
|
||||
ino_t ino;
|
||||
int duration;
|
||||
};
|
||||
|
||||
#define FSM_REQ_TCSETATTR 62
|
||||
struct fsm_req_tcsetattr
|
||||
{
|
||||
ino_t ino;
|
||||
int actions;
|
||||
struct termios tio;
|
||||
};
|
||||
|
||||
#define FSM_MSG_NUM 63
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013, 2016.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
|
@ -27,6 +27,9 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sortix/ioctl.h>
|
||||
#include <sortix/winsize.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -31,12 +31,14 @@
|
|||
|
||||
#include <sys/__/types.h>
|
||||
|
||||
#if __USE_SORTIX
|
||||
#include <sortix/termios.h>
|
||||
#if __USE_SORTIX
|
||||
#include <sortix/winsize.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#ifndef __pid_t_defined
|
||||
#define __pid_t_defined
|
||||
typedef __pid_t pid_t;
|
||||
#endif
|
||||
|
||||
#if __USE_SORTIX
|
||||
|
@ -45,13 +47,31 @@ extern "C" {
|
|||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __USE_SORTIX
|
||||
#ifndef __ssize_t_defined
|
||||
#define __ssize_t_defined
|
||||
typedef __ssize_t ssize_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
speed_t cfgetispeed(const struct termios*);
|
||||
speed_t cfgetospeed(const struct termios*);
|
||||
int cfsetispeed(struct termios*, speed_t);
|
||||
int cfsetospeed(struct termios*, speed_t);
|
||||
int tcdrain(int);
|
||||
int tcflow(int, int);
|
||||
int tcflush(int, int);
|
||||
int tcgetattr(int, struct termios*);
|
||||
pid_t tcgetsid(int);
|
||||
int tcsendbreak(int, int);
|
||||
int tcsetattr(int, int, const struct termios*);
|
||||
|
||||
/* Functions that are Sortix extensions. */
|
||||
#if __USE_SORTIX
|
||||
ssize_t tcgetblob(int, const char*, void*, size_t);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013, 2016.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
|
@ -25,15 +25,25 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
DEFN_SYSCALL3(int, sys_ioctl, SYSCALL_IOCTL, int, int, void*);
|
||||
DEFN_SYSCALL3(int, sys_ioctl, SYSCALL_IOCTL, int, int, uintptr_t);
|
||||
|
||||
extern "C" int ioctl(int fd, int request, ...)
|
||||
{
|
||||
uintptr_t arg;
|
||||
va_list ap;
|
||||
va_start(ap, request);
|
||||
void* ptr = va_arg(ap, void*);
|
||||
switch ( __IOCTL_TYPE(request) )
|
||||
{
|
||||
case __IOCTL_TYPE_VOID: arg = 0; break;
|
||||
case __IOCTL_TYPE_INT: arg = (uintptr_t) va_arg(ap, int); break;
|
||||
case __IOCTL_TYPE_LONG: arg = (uintptr_t) va_arg(ap, long); break;
|
||||
case __IOCTL_TYPE_PTR: arg = (uintptr_t) va_arg(ap, void*); break;
|
||||
default: return errno = EINVAL, -1;
|
||||
}
|
||||
va_end(ap);
|
||||
return sys_ioctl(fd, request, ptr);
|
||||
return sys_ioctl(fd, request, arg);
|
||||
}
|
||||
|
|
30
libc/termios/cfgetispeed.cpp
Normal file
30
libc/termios/cfgetispeed.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/cfgetispeed.cpp
|
||||
Get termios input speed.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
extern "C" speed_t cfgetispeed(const struct termios* tio)
|
||||
{
|
||||
return tio->c_ispeed;
|
||||
}
|
30
libc/termios/cfgetospeed.cpp
Normal file
30
libc/termios/cfgetospeed.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/cfgetospeed.cpp
|
||||
Get termios output speed.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
extern "C" speed_t cfgetospeed(const struct termios* tio)
|
||||
{
|
||||
return tio->c_ospeed;
|
||||
}
|
31
libc/termios/cfsetispeed.cpp
Normal file
31
libc/termios/cfsetispeed.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/cfsetispeed.cpp
|
||||
Set termios input speed.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
extern "C" int cfsetispeed(struct termios* tio, speed_t speed)
|
||||
{
|
||||
tio->c_ispeed = speed;
|
||||
return 0;
|
||||
}
|
31
libc/termios/cfsetospeed.cpp
Normal file
31
libc/termios/cfsetospeed.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/cfsetospeed.cpp
|
||||
Set termios output speed.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
extern "C" int cfsetospeed(struct termios* tio, speed_t speed)
|
||||
{
|
||||
tio->c_ospeed = speed;
|
||||
return 0;
|
||||
}
|
34
libc/termios/tcdrain.cpp
Normal file
34
libc/termios/tcdrain.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/tcdrain.cpp
|
||||
Wait for transmission of output.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
DEFN_SYSCALL1(int, sys_tcdrain, SYSCALL_TCDRAIN, int);
|
||||
|
||||
extern "C" int tcdrain(int fd)
|
||||
{
|
||||
return sys_tcdrain(fd);
|
||||
}
|
34
libc/termios/tcflow.cpp
Normal file
34
libc/termios/tcflow.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/tcflow.cpp
|
||||
Suspend or restart the transmission or reception of data.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
DEFN_SYSCALL2(int, sys_tcflow, SYSCALL_TCFLOW, int, int);
|
||||
|
||||
extern "C" int tcflow(int fd, int action)
|
||||
{
|
||||
return sys_tcflow(fd, action);
|
||||
}
|
34
libc/termios/tcflush.cpp
Normal file
34
libc/termios/tcflush.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/tcflush.cpp
|
||||
Flush non-transmitted output data, non-read input data, or both.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
DEFN_SYSCALL2(int, sys_tcflush, SYSCALL_TCFLUSH, int, int);
|
||||
|
||||
extern "C" int tcflush(int fd, int queue_selector)
|
||||
{
|
||||
return sys_tcflush(fd, queue_selector);
|
||||
}
|
34
libc/termios/tcgetattr.cpp
Normal file
34
libc/termios/tcgetattr.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/tcgetattr.cpp
|
||||
Get the parameters associated with the terminal.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
DEFN_SYSCALL2(int, sys_tcgetattr, SYSCALL_TCGETATTR, int, struct termios*);
|
||||
|
||||
extern "C" int tcgetattr(int fd, struct termios* tio)
|
||||
{
|
||||
return sys_tcgetattr(fd, tio);
|
||||
}
|
34
libc/termios/tcgetsid.cpp
Normal file
34
libc/termios/tcgetsid.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/tcgetsid.cpp
|
||||
Get terminal session id.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
DEFN_SYSCALL1(int, sys_tcgetsid, SYSCALL_TCGETSID, int);
|
||||
|
||||
extern "C" pid_t tcgetsid(int fd)
|
||||
{
|
||||
return sys_tcgetsid(fd);
|
||||
}
|
34
libc/termios/tcsendbreak.cpp
Normal file
34
libc/termios/tcsendbreak.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/tcsendbreak.cpp
|
||||
Send a break for a specific duration.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
DEFN_SYSCALL2(int, sys_tcsendbreak, SYSCALL_TCSENDBREAK, int, int);
|
||||
|
||||
extern "C" int tcsendbreak(int fd, int duration)
|
||||
{
|
||||
return sys_tcsendbreak(fd, duration);
|
||||
}
|
34
libc/termios/tcsetattr.cpp
Normal file
34
libc/termios/tcsetattr.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2015.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
termios/tcsetattr.cpp
|
||||
Set the parameters associated with the terminal.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
DEFN_SYSCALL3(int, sys_tcsetattr, SYSCALL_TCSETATTR, int, int, const struct termios*);
|
||||
|
||||
extern "C" int tcsetattr(int fd, int actions, const struct termios* tio)
|
||||
{
|
||||
return sys_tcsetattr(fd, actions, tio);
|
||||
}
|
|
@ -35,13 +35,6 @@
|
|||
#include "editline.h"
|
||||
#include "showline.h"
|
||||
|
||||
static const unsigned int NORMAL_TERMMODE =
|
||||
TERMMODE_UNICODE |
|
||||
TERMMODE_SIGNAL |
|
||||
TERMMODE_UTF8 |
|
||||
TERMMODE_LINEBUFFER |
|
||||
TERMMODE_ECHO;
|
||||
|
||||
void edit_line_show(struct edit_line* edit_state)
|
||||
{
|
||||
size_t line_length = 0;
|
||||
|
@ -564,7 +557,7 @@ void edit_line_codepoint(struct edit_line* edit_state, wchar_t wc)
|
|||
return;
|
||||
}
|
||||
|
||||
if ( wc == L'\b' )
|
||||
if ( wc == L'\b' || wc == 127 )
|
||||
return;
|
||||
if ( wc == L'\t' )
|
||||
return;
|
||||
|
@ -617,5 +610,5 @@ void edit_line(struct edit_line* edit_state)
|
|||
show_line_finish(&edit_state->show_state);
|
||||
}
|
||||
|
||||
settermmode(edit_state->in_fd, NORMAL_TERMMODE);
|
||||
settermmode(edit_state->in_fd, TERMMODE_NORMAL);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
@ -155,7 +156,12 @@ static bool ForkAndWait()
|
|||
{
|
||||
int status;
|
||||
waitpid(child_pid, &status, 0);
|
||||
sigset_t oldset, sigttou;
|
||||
sigemptyset(&sigttou);
|
||||
sigaddset(&sigttou, SIGTTOU);
|
||||
sigprocmask(SIG_BLOCK, &sigttou, &oldset);
|
||||
tcsetpgrp(0, getpgid(0));
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
settermmode(0, old_termmode);
|
||||
return false;
|
||||
}
|
||||
|
@ -166,13 +172,18 @@ static bool ForkAndWait()
|
|||
open("/dev/tty", O_WRONLY);
|
||||
open("/dev/tty", O_WRONLY);
|
||||
setpgid(0, 0);
|
||||
sigset_t oldset, sigttou;
|
||||
sigemptyset(&sigttou);
|
||||
sigaddset(&sigttou, SIGTTOU);
|
||||
sigprocmask(SIG_BLOCK, &sigttou, &oldset);
|
||||
tcsetpgrp(0, getpgid(0));
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
#if 1 /* Magic to somehow fix a weird keyboard-related bug nortti has. */
|
||||
settermmode(0, TERMMODE_UNICODE | TERMMODE_SIGNAL | TERMMODE_UTF8 | TERMMODE_LINEBUFFER | TERMMODE_ECHO | TERMMODE_NONBLOCK);
|
||||
settermmode(0, TERMMODE_NORMAL | TERMMODE_NONBLOCK);
|
||||
char c;
|
||||
while ( 0 <= read(0, &c, sizeof(c)) );
|
||||
#endif
|
||||
settermmode(0, TERMMODE_UNICODE | TERMMODE_SIGNAL | TERMMODE_UTF8 | TERMMODE_LINEBUFFER | TERMMODE_ECHO);
|
||||
settermmode(0, TERMMODE_NORMAL);
|
||||
printf("\e[m\e[2J\e[H");
|
||||
fflush(stdout);
|
||||
fsync(0);
|
||||
|
@ -1719,7 +1730,7 @@ void HandleCodepoint(uint32_t codepoint, struct Desktop* desktop)
|
|||
size_t column = 0;
|
||||
while ( desktop->command[column] )
|
||||
column++;
|
||||
if ( c == '\b' )
|
||||
if ( c == '\b' || c == 127 )
|
||||
{
|
||||
if ( column )
|
||||
desktop->command[column-1] = '\0';
|
||||
|
@ -1918,9 +1929,6 @@ static int CreateKeyboardConnection()
|
|||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
setpgid(0, 0);
|
||||
tcsetpgrp(0, getpgid(0));
|
||||
|
||||
struct stat st;
|
||||
if ( stat("/etc/rune-enable", &st) == 0 )
|
||||
use_runes = true, configured_use_runes = true;
|
||||
|
|
Loading…
Reference in a new issue