Added a kind-of-working openpty()

This commit is contained in:
Mark
2020-01-03 22:13:38 +02:00
parent ce81c6fa9e
commit dd8564a134
9 changed files with 238 additions and 4 deletions
+2 -1
View File
@@ -68,7 +68,8 @@ OBJS+=$(O)/sys/debug.o \
$(O)/sys/net/in.o \
$(O)/sys/net/netdev.o \
$(O)/sys/vfs/devfs.o \
$(O)/sys/vfs/pseudo.o
$(O)/sys/vfs/pseudo.o \
$(O)/sys/vfs/pty.o
ifeq ($(VESA_ENABLE),1)
OBJS+=$(O)/sys/psf.o \
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "sys/fs/node.h"
#include "sys/ring.h"
#include "sys/chr.h"
struct pty {
int number;
vnode_t *master;
vnode_t *slave;
// TODO: winsize/termios
struct chrdev dev_master;
struct chrdev dev_slave;
// Slave reads
// Master writes
struct ring ring_input;
// Slave writes
// Master reads
struct ring ring_output;
int owner_pid;
};
struct pty *pty_create(void);
+2
View File
@@ -18,4 +18,6 @@
#define SYSCALL_NR_EXIT 60
#define SYSCALL_NR_KILL 62
#define SYSCALL_NR_GETTIMEOFDAY 96
#define SYSCALL_NRX_OPENPTY 118
#define SYSCALL_NRX_SIGRET 119
+2 -2
View File
@@ -227,8 +227,8 @@ static void process_csi(void) {
break;
case 'f':
// Set cursor position
y = (esc_argv[0] - 1) % con_width;
x = (esc_argv[1] - 1) % (con_height - 1);
y = (esc_argv[0] - 1) % con_height;
x = (esc_argv[1] - 1) % (con_width - 1);
amd64_con_moveto(y, x);
break;
case 's':
+49
View File
@@ -12,6 +12,7 @@
#include "sys/tty.h"
#include "sys/amd64/mm/phys.h"
#include "sys/amd64/mm/map.h"
#include "sys/fs/pty.h"
#include "sys/time.h"
static ssize_t sys_read(int fd, void *buf, size_t lim);
@@ -29,6 +30,9 @@ static int sys_brk(void *ptr);
static int sys_nanosleep(const struct timespec *req, struct timespec *rem);
static int sys_gettimeofday(struct timeval *tv, struct timezone *tz);
// TODO: const struct termios *termp, const struct winsize *winp
static int sys_openpty(int *master, int *slave);
extern int sys_execve(const char *filename, const char *const argv[], const char *const envp[]);
// Non-compliant with linux style, but fuck'em, it just works
@@ -80,9 +84,12 @@ intptr_t amd64_syscall(uintptr_t rdi, uintptr_t rsi, uintptr_t rdx, uintptr_t rc
return sys_kill((int) rdi, (int) rsi);
case SYSCALL_NR_GETTIMEOFDAY:
return sys_gettimeofday((struct timeval *) rdi, (struct timezone *) rsi);
case SYSCALL_NRX_SIGRET:
sys_sigret();
return 0;
case SYSCALL_NRX_OPENPTY:
return sys_openpty((int *) rdi, (int *) rsi);
default:
kerror("unknown syscall: %u\n", rax);
@@ -208,6 +215,48 @@ static int sys_open(const char *filename, int flags, int mode) {
}
}
static int sys_openpty(int *master, int *slave) {
struct thread *thr = get_cpu()->thread;
_assert(thr);
// Find two free file descriptors
int fd_master = -1, fd_slave = -1;
int res;
for (int i = 0; i < 4; ++i) {
if (!thr->fds[i].vnode) {
if (fd_master == -1) {
fd_master = i;
continue;
}
fd_slave = i;
break;
}
}
if (fd_master == -1 || fd_slave == -1) {
return -EMFILE;
}
struct ofile *of_master = &thr->fds[fd_master];
struct ofile *of_slave = &thr->fds[fd_slave];
struct pty *pty = pty_create();
_assert(pty);
of_master->vnode = pty->master;
of_master->flags = O_RDWR;
of_master->pos = 0;
of_slave->vnode = pty->slave;
of_slave->flags = O_RDWR;
of_slave->pos = 0;
*master = fd_master;
*slave = fd_slave;
return 0;
}
static void sys_close(int fd) {
if (fd >= 4 || fd < 0) {
return;
+148
View File
@@ -0,0 +1,148 @@
#include "sys/fs/pty.h"
#include "sys/fs/ofile.h"
#include "sys/fs/node.h"
#include "sys/amd64/cpu.h"
#include "sys/string.h"
#include "sys/assert.h"
#include "sys/debug.h"
#include "sys/errno.h"
#include "sys/heap.h"
#define PTY_RING_SIZE 256
static ssize_t pty_master_write(struct chrdev *dev, const void *buf, size_t count, size_t off);
static ssize_t pty_master_read(struct chrdev *dev, void *buf, size_t count, size_t off);
static ssize_t pty_slave_write(struct chrdev *dev, const void *buf, size_t count, size_t off);
static ssize_t pty_slave_read(struct chrdev *dev, void *buf, size_t count, size_t off);
//static struct chrdev pty_master_dev = {
// .read = pty_master_read,
// .write = pty_master_write
//};
//
//static struct chrdev pty_slave_dev = {
// .read = pty_slave_read,
// .write = pty_slave_write
//};
static ssize_t pty_slave_write(struct chrdev *dev, const void *buf, size_t off, size_t count) {
// Slave writes -> pty output -> Master reads
// AS-IS
struct pty *pty = dev->dev_data;
_assert(pty);
int res = 0;
for (size_t i = 0; i < count; ++i) {
if ((res = ring_putc(&pty->ring_output, ((const char *) buf)[i])) < 0) {
break;
}
}
return (res < 0) ? res : (ssize_t) count;
}
static ssize_t pty_slave_read(struct chrdev *dev, void *buf, size_t off, size_t count) {
// Slave reads <- pty input <- Master writes
// TODO: process stuff like ^C/^D etc.
struct pty *pty = dev->dev_data;
_assert(pty);
char ibuf[16];
size_t rem = count;
size_t p = 0;
if (count == 0) {
return 0;
}
while (rem) {
ssize_t rd = ring_read(get_cpu()->thread, &pty->ring_output, ibuf, MIN(16, rem));
if (rd < 0) {
break;
}
memcpy((char *) buf + p, ibuf, rd);
rem -= rd;
}
return p;
}
static ssize_t pty_master_write(struct chrdev *dev, const void *buf, size_t pos, size_t count) {
// Master writes -> pty input -> Slave reads
// TODO: process stuff like CR/LF conversion etc.
struct pty *pty = dev->dev_data;
_assert(pty);
int res = 0;
for (size_t i = 0; i < count; ++i) {
if ((res = ring_putc(&pty->ring_input, ((const char *) buf)[i])) < 0) {
break;
}
}
return (res < 0) ? res : (ssize_t) count;
}
static ssize_t pty_master_read(struct chrdev *dev, void *buf, size_t off, size_t count) {
// Master reads <- pty output <- Slave writes
// AS-IS
struct pty *pty = dev->dev_data;
_assert(pty);
char ibuf[16];
size_t rem = count;
size_t p = 0;
if (count == 0) {
return 0;
}
while (rem) {
ssize_t rd = ring_read(get_cpu()->thread, &pty->ring_output, ibuf, MIN(16, rem));
if (rd < 0) {
break;
}
memcpy((char *) buf + p, ibuf, rd);
rem -= rd;
}
return p;
}
struct pty *pty_create(void) {
struct pty *pty = kmalloc(sizeof(struct pty));
_assert(pty);
ring_init(&pty->ring_input, PTY_RING_SIZE);
ring_init(&pty->ring_output, PTY_RING_SIZE);
pty->dev_master.read = pty_master_read;
pty->dev_master.write = pty_master_write;
pty->dev_master.dev_data = pty;
pty->dev_slave.read = pty_slave_read;
pty->dev_slave.write = pty_slave_write;
pty->dev_slave.dev_data = pty;
vnode_t *pty_master = kmalloc(sizeof(vnode_t));
_assert(pty_master);
vnode_t *pty_slave = kmalloc(sizeof(vnode_t));
_assert(pty_slave);
// TODO: add these to devfs
pty_master->refcount = 0;
pty_master->fs = NULL;
pty_master->tree_node = NULL;
pty_master->type = VN_CHR;
pty_master->dev = &pty->dev_master;
pty_slave->refcount = 0;
pty_slave->fs = NULL;
pty_slave->tree_node = NULL;
pty_slave->type = VN_CHR;
pty_slave->dev = &pty->dev_slave;
pty->master = pty_master;
pty->slave = pty_slave;
return pty;
}
+6 -1
View File
@@ -183,7 +183,12 @@ static int b_curs(const char *arg) {
while (1) {
// Draw some kind of status bar
curs_set(25, 1);
printf("\033[7m This is statusbar\033[K\033[0m");
printf("\033[7m This is statusbar\033[K");
if (c >= ' ') {
curs_set(25, 79);
printf("%c\033[0m", c);
}
printf("\033[0m");
curs_set(1, 1);
if (read(STDIN_FILENO, &c, 1) < 0) {
+1
View File
@@ -21,5 +21,6 @@ int getpid(void);
int chdir(const char *filename);
char *getcwd(char *buf, size_t size);
int nanosleep(const struct timespec *req, struct timespec *rem);
int openpty(int *amaster, int *aslave);
__attribute__((noreturn)) void exit(int code);
+4
View File
@@ -129,6 +129,10 @@ int nanosleep(const struct timespec *req, struct timespec *rem) {
return SET_ERRNO(int, ASM_SYSCALL2(SYSCALL_NR_NANOSLEEP, req, rem));
}
int openpty(int *master, int *slave) {
return SET_ERRNO(int, ASM_SYSCALL2(SYSCALL_NRX_OPENPTY, master, slave));
}
// Although sbrk() is implemented in userspace, I guess it should also be here
void *sbrk(intptr_t inc) {
if (inc == 0) {