ICANON support (still a bit rough)
This is a massive hack and I admit it.
This commit is contained in:
parent
40f0c41932
commit
720a62d6aa
128
kernel/fs/tty.c
128
kernel/fs/tty.c
@ -29,6 +29,7 @@ typedef struct pty {
|
|||||||
|
|
||||||
char * canon_buffer;
|
char * canon_buffer;
|
||||||
size_t canon_bufsize;
|
size_t canon_bufsize;
|
||||||
|
size_t canon_buflen;
|
||||||
|
|
||||||
pid_t ct_proc; /* Controlling process (shell) */
|
pid_t ct_proc; /* Controlling process (shell) */
|
||||||
pid_t fg_proc; /* Foreground process (might also be shell) */
|
pid_t fg_proc; /* Foreground process (might also be shell) */
|
||||||
@ -37,6 +38,97 @@ typedef struct pty {
|
|||||||
|
|
||||||
list_t * pty_list = NULL;
|
list_t * pty_list = NULL;
|
||||||
|
|
||||||
|
#define IN(character) ring_buffer_write(pty->in, 1, (uint8_t *)&(character))
|
||||||
|
#define OUT(character) ring_buffer_write(pty->out, 1, (uint8_t *)&(character))
|
||||||
|
|
||||||
|
static void dump_input_buffer(pty_t * pty) {
|
||||||
|
char * c = pty->canon_buffer;
|
||||||
|
while (pty->canon_buflen > 0) {
|
||||||
|
IN(*c);
|
||||||
|
pty->canon_buflen--;
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output_process(pty_t * pty, uint8_t c) {
|
||||||
|
if (c == '\n' && (pty->tios.c_oflag & ONLCR)) {
|
||||||
|
uint8_t d = '\r';
|
||||||
|
OUT(d);
|
||||||
|
}
|
||||||
|
OUT(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void input_process(pty_t * pty, uint8_t c) {
|
||||||
|
if (pty->tios.c_lflag & ICANON) {
|
||||||
|
debug_print(INFO, "Processing for character %d in canon mode", c);
|
||||||
|
if (c == pty->tios.c_cc[VKILL]) {
|
||||||
|
while (pty->canon_buflen > 0) {
|
||||||
|
pty->canon_buflen--;
|
||||||
|
pty->canon_buffer[pty->canon_buflen] = '\0';
|
||||||
|
if (pty->tios.c_lflag & ECHO) {
|
||||||
|
output_process(pty, '\010');
|
||||||
|
output_process(pty, ' ');
|
||||||
|
output_process(pty, '\010');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c == pty->tios.c_cc[VERASE]) {
|
||||||
|
/* Backspace */
|
||||||
|
if (pty->canon_buflen > 0) {
|
||||||
|
pty->canon_buflen--;
|
||||||
|
pty->canon_buffer[pty->canon_buflen] = '\0';
|
||||||
|
if (pty->tios.c_lflag & ECHO) {
|
||||||
|
output_process(pty, '\010');
|
||||||
|
output_process(pty, ' ');
|
||||||
|
output_process(pty, '\010');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c == pty->tios.c_cc[VINTR]) {
|
||||||
|
if (pty->tios.c_lflag & ECHO) {
|
||||||
|
output_process(pty, '^');
|
||||||
|
output_process(pty, '@' + c);
|
||||||
|
output_process(pty, '\n');
|
||||||
|
}
|
||||||
|
if (pty->fg_proc) {
|
||||||
|
send_signal(pty->fg_proc, SIGINT);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c == pty->tios.c_cc[VQUIT]) {
|
||||||
|
if (pty->tios.c_lflag & ECHO) {
|
||||||
|
output_process(pty, '^');
|
||||||
|
output_process(pty, '@' + c);
|
||||||
|
output_process(pty, '\n');
|
||||||
|
}
|
||||||
|
if (pty->fg_proc) {
|
||||||
|
send_signal(pty->fg_proc, SIGQUIT);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pty->canon_buffer[pty->canon_buflen] = c;
|
||||||
|
if (pty->tios.c_lflag & ECHO) {
|
||||||
|
output_process(pty, c);
|
||||||
|
}
|
||||||
|
if (pty->canon_buffer[pty->canon_buflen] == '\n') {
|
||||||
|
pty->canon_buflen++;
|
||||||
|
dump_input_buffer(pty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pty->canon_buflen == pty->canon_bufsize) {
|
||||||
|
dump_input_buffer(pty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pty->canon_buflen++;
|
||||||
|
return;
|
||||||
|
} else if (pty->tios.c_lflag & ECHO) {
|
||||||
|
output_process(pty, c);
|
||||||
|
}
|
||||||
|
IN(c);
|
||||||
|
}
|
||||||
|
|
||||||
int pty_ioctl(pty_t * pty, int request, void * argp) {
|
int pty_ioctl(pty_t * pty, int request, void * argp) {
|
||||||
debug_print(WARNING, "Incoming IOCTL request %d", request);
|
debug_print(WARNING, "Incoming IOCTL request %d", request);
|
||||||
switch (request) {
|
switch (request) {
|
||||||
@ -64,11 +156,25 @@ int pty_ioctl(pty_t * pty, int request, void * argp) {
|
|||||||
validate(argp);
|
validate(argp);
|
||||||
memcpy(argp, &pty->tios, sizeof(struct termios));
|
memcpy(argp, &pty->tios, sizeof(struct termios));
|
||||||
return 0;
|
return 0;
|
||||||
|
case TIOCSPGRP:
|
||||||
|
if (!argp) return -1;
|
||||||
|
validate(argp);
|
||||||
|
pty->fg_proc = *(pid_t *)argp;
|
||||||
|
return 0;
|
||||||
|
case TIOCGPGRP:
|
||||||
|
if (!argp) return -1;
|
||||||
|
validate(argp);
|
||||||
|
*(pid_t *)argp = pty->fg_proc;
|
||||||
|
return 0;
|
||||||
case TCSETS:
|
case TCSETS:
|
||||||
case TCSETSW:
|
case TCSETSW:
|
||||||
case TCSETSF:
|
case TCSETSF:
|
||||||
if (!argp) return -1;
|
if (!argp) return -1;
|
||||||
validate(argp);
|
validate(argp);
|
||||||
|
if (!(((struct termios *)argp)->c_lflag & ICANON) && (pty->tios.c_lflag & ICANON)) {
|
||||||
|
/* Switch out of canonical mode, the dump the input buffer */
|
||||||
|
|
||||||
|
}
|
||||||
memcpy(&pty->tios, argp, sizeof(struct termios));
|
memcpy(&pty->tios, argp, sizeof(struct termios));
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
@ -77,24 +183,6 @@ int pty_ioctl(pty_t * pty, int request, void * argp) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IN(character) ring_buffer_write(pty->in, 1, (uint8_t *)&(character))
|
|
||||||
#define OUT(character) ring_buffer_write(pty->out, 1, (uint8_t *)&(character))
|
|
||||||
|
|
||||||
static void output_process(pty_t * pty, uint8_t c) {
|
|
||||||
if (c == '\n' && (pty->tios.c_oflag & ONLCR)) {
|
|
||||||
uint8_t d = '\r';
|
|
||||||
OUT(d);
|
|
||||||
}
|
|
||||||
OUT(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void input_process(pty_t * pty, uint8_t c) {
|
|
||||||
if (pty->tios.c_lflag & ECHO) {
|
|
||||||
output_process(pty, c);
|
|
||||||
}
|
|
||||||
IN(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
uint32_t read_pty_master(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t *buffer) {
|
uint32_t read_pty_master(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t *buffer) {
|
||||||
@ -269,6 +357,10 @@ pty_t * pty_new(struct winsize * size) {
|
|||||||
pty->tios.c_cc[VSUSP] = 26; /* ^Z */
|
pty->tios.c_cc[VSUSP] = 26; /* ^Z */
|
||||||
pty->tios.c_cc[VTIME] = 0;
|
pty->tios.c_cc[VTIME] = 0;
|
||||||
|
|
||||||
|
pty->canon_buffer = malloc(TTY_BUFFER_SIZE);
|
||||||
|
pty->canon_bufsize = TTY_BUFFER_SIZE;
|
||||||
|
pty->canon_buflen = 0;
|
||||||
|
|
||||||
return pty;
|
return pty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,6 +359,8 @@ typedef struct {
|
|||||||
|
|
||||||
void handle_signal(process_t *, signal_t *);
|
void handle_signal(process_t *, signal_t *);
|
||||||
|
|
||||||
|
int send_signal(pid_t process, uint32_t signal);
|
||||||
|
|
||||||
#define USER_STACK_BOTTOM 0xAFF00000
|
#define USER_STACK_BOTTOM 0xAFF00000
|
||||||
#define USER_STACK_TOP 0xB0000000
|
#define USER_STACK_TOP 0xB0000000
|
||||||
#define SHM_START 0xB0000000
|
#define SHM_START 0xB0000000
|
||||||
|
@ -422,7 +422,7 @@ static int uname(struct utsname * name) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_signal(pid_t process, uint32_t signal) {
|
int send_signal(pid_t process, uint32_t signal) {
|
||||||
process_t * receiver = process_from_pid(process);
|
process_t * receiver = process_from_pid(process);
|
||||||
|
|
||||||
if (!receiver) {
|
if (!receiver) {
|
||||||
|
@ -913,12 +913,14 @@ _done:
|
|||||||
}
|
}
|
||||||
exit(i);
|
exit(i);
|
||||||
} else {
|
} else {
|
||||||
|
tcsetpgrp(0, f);
|
||||||
int ret_code = 0;
|
int ret_code = 0;
|
||||||
if (!nowait) {
|
if (!nowait) {
|
||||||
child = f;
|
child = f;
|
||||||
waitpid(f, &ret_code, 0);
|
waitpid(f, &ret_code, 0);
|
||||||
child = 0;
|
child = 0;
|
||||||
}
|
}
|
||||||
|
tcsetpgrp(0, getpid());
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user