diff --git a/kernel/descriptor.cpp b/kernel/descriptor.cpp index 99e05592..5f65006b 100644 --- a/kernel/descriptor.cpp +++ b/kernel/descriptor.cpp @@ -548,6 +548,11 @@ ssize_t Descriptor::readlink(ioctx_t* ctx, char* buf, size_t bufsize) return vnode->readlink(ctx, buf, bufsize); } +int Descriptor::tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp) +{ + return vnode->tcgetwincurpos(ctx, wcp); +} + int Descriptor::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) { return vnode->tcgetwinsize(ctx, ws); diff --git a/kernel/fs/user.cpp b/kernel/fs/user.cpp index e4451340..b9c334a1 100644 --- a/kernel/fs/user.cpp +++ b/kernel/fs/user.cpp @@ -212,6 +212,7 @@ public: virtual int symlink(ioctx_t* ctx, const char* oldname, const char* filename); virtual ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); + virtual int tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp); virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); virtual int tcsetpgrp(ioctx_t* ctx, pid_t pgid); virtual pid_t tcgetpgrp(ioctx_t* ctx); @@ -1101,6 +1102,23 @@ ssize_t Unode::readlink(ioctx_t* ctx, char* buf, size_t bufsiz) return ret; } +int Unode::tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp) +{ + Channel* channel = server->Connect(); + if ( !channel ) + return -1; + int ret = -1; + struct fsm_req_tcgetwincurpos msg; + struct fsm_resp_tcgetwincurpos resp; + msg.ino = ino; + if ( SendMessage(channel, FSM_REQ_TCGETWINCURPOS, &msg, sizeof(msg)) && + RecvMessage(channel, FSM_RESP_TCGETWINCURPOS, &resp, sizeof(resp)) && + ctx->copy_to_dest(wcp, &resp.pos, sizeof(*wcp)) ) + ret = 0; + channel->KernelClose(); + return ret; +} + int Unode::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) { Channel* channel = server->Connect(); diff --git a/kernel/include/sortix/kernel/descriptor.h b/kernel/include/sortix/kernel/descriptor.h index 4fc6fa2b..9d89b831 100644 --- a/kernel/include/sortix/kernel/descriptor.h +++ b/kernel/include/sortix/kernel/descriptor.h @@ -35,6 +35,7 @@ #include struct stat; +struct wincurpos; struct winsize; struct kernel_dirent; @@ -77,6 +78,7 @@ public: int rmdir(ioctx_t* ctx, const char* filename); int symlink(ioctx_t* ctx, const char* oldname, const char* filename); ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); + int tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp); int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); int tcsetpgrp(ioctx_t* ctx, pid_t pgid); pid_t tcgetpgrp(ioctx_t* ctx); diff --git a/kernel/include/sortix/kernel/inode.h b/kernel/include/sortix/kernel/inode.h index e463c28d..38f1bdfb 100644 --- a/kernel/include/sortix/kernel/inode.h +++ b/kernel/include/sortix/kernel/inode.h @@ -35,6 +35,7 @@ #include struct stat; +struct wincurpos; struct winsize; struct kernel_dirent; @@ -86,6 +87,7 @@ public: virtual int symlink(ioctx_t* ctx, const char* oldname, const char* filename) = 0; virtual ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz) = 0; + virtual int tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp) = 0; virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws) = 0; virtual int tcsetpgrp(ioctx_t* ctx, pid_t pgid) = 0; virtual pid_t tcgetpgrp(ioctx_t* ctx) = 0; @@ -164,6 +166,7 @@ public: virtual int symlink(ioctx_t* ctx, const char* oldname, const char* filename); virtual ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); + virtual int tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp); virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); virtual int tcsetpgrp(ioctx_t* ctx, pid_t pgid); virtual pid_t tcgetpgrp(ioctx_t* ctx); diff --git a/kernel/include/sortix/kernel/log.h b/kernel/include/sortix/kernel/log.h index 532ed43e..efa0d742 100644 --- a/kernel/include/sortix/kernel/log.h +++ b/kernel/include/sortix/kernel/log.h @@ -36,6 +36,7 @@ namespace Log { extern size_t (*device_callback)(void*, const char*, size_t); extern size_t (*device_width)(void*); extern size_t (*device_height)(void*); +extern void (*device_get_cursor)(void*, size_t*, size_t*); extern bool (*device_sync)(void*); extern void* device_pointer; extern bool (*emergency_device_is_impaired)(void*); @@ -44,6 +45,7 @@ extern void (*emergency_device_reset)(void*); extern size_t (*emergency_device_callback)(void*, const char*, size_t); extern size_t (*emergency_device_width)(void*); extern size_t (*emergency_device_height)(void*); +extern void (*emergency_device_get_cursor)(void*, size_t*, size_t*); extern bool (*emergency_device_sync)(void*); extern void* emergency_device_pointer; @@ -64,6 +66,11 @@ inline size_t Height() return device_height(device_pointer); } +inline void GetCursor(size_t* col, size_t* row) +{ + return device_get_cursor(device_pointer, col, row); +} + inline bool Sync() { return device_sync(device_pointer); diff --git a/kernel/include/sortix/kernel/vnode.h b/kernel/include/sortix/kernel/vnode.h index 5c6c98e6..f262a262 100644 --- a/kernel/include/sortix/kernel/vnode.h +++ b/kernel/include/sortix/kernel/vnode.h @@ -25,11 +25,16 @@ #ifndef INCLUDE_SORTIX_KERNEL_VNODE_H #define INCLUDE_SORTIX_KERNEL_VNODE_H +#include + +#include + #include #include struct stat; +struct wincurpos; struct winsize; struct kernel_dirent; @@ -74,6 +79,7 @@ public: int symlink(ioctx_t* ctx, const char* oldname, const char* filename); ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); int fsbind(ioctx_t* ctx, Vnode* node, int flags); + int tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp); int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); int tcsetpgrp(ioctx_t* ctx, pid_t pgid); pid_t tcgetpgrp(ioctx_t* ctx); diff --git a/kernel/include/sortix/syscallnum.h b/kernel/include/sortix/syscallnum.h index 62968034..d9301319 100644 --- a/kernel/include/sortix/syscallnum.h +++ b/kernel/include/sortix/syscallnum.h @@ -145,6 +145,7 @@ #define SYSCALL_PRLIMIT 121 #define SYSCALL_DUP3 122 #define SYSCALL_SYMLINKAT 123 -#define SYSCALL_MAX_NUM 124 /* index of highest constant + 1 */ +#define SYSCALL_TCGETWINCURPOS 124 +#define SYSCALL_MAX_NUM 125 /* index of highest constant + 1 */ #endif diff --git a/kernel/include/sortix/termios.h b/kernel/include/sortix/termios.h index b124a88f..bcb30f15 100644 --- a/kernel/include/sortix/termios.h +++ b/kernel/include/sortix/termios.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. This file is part of Sortix. @@ -22,13 +22,27 @@ *******************************************************************************/ -#ifndef SORTIX_TERMIOS_H -#define SORTIX_TERMIOS_H +#ifndef INCLUDE_SORTIX_TERMIOS_H +#define INCLUDE_SORTIX_TERMIOS_H #include +#include + __BEGIN_DECLS +#ifndef __size_t_defined +#define __size_t_defined +#define __need_size_t +#include +#endif + +struct wincurpos +{ + size_t wcp_row; + size_t wcp_col; +}; + struct winsize { size_t ws_row; diff --git a/kernel/inode.cpp b/kernel/inode.cpp index 293f5b04..d929da3c 100644 --- a/kernel/inode.cpp +++ b/kernel/inode.cpp @@ -258,6 +258,13 @@ ssize_t AbstractInode::readlink(ioctx_t* /*ctx*/, char* /*buf*/, return errno = EINVAL, -1; } +int AbstractInode::tcgetwincurpos(ioctx_t* /*ctx*/, struct wincurpos* /*wcp*/) +{ + if ( inode_type == INODE_TYPE_TTY ) + return errno = EBADF, -1; + return errno = ENOTTY, -1; +} + int AbstractInode::tcgetwinsize(ioctx_t* /*ctx*/, struct winsize* /*ws*/) { if ( inode_type == INODE_TYPE_TTY ) diff --git a/kernel/io.cpp b/kernel/io.cpp index f462bc6a..23a82f78 100644 --- a/kernel/io.cpp +++ b/kernel/io.cpp @@ -652,6 +652,16 @@ static int sys_isatty(int fd) return desc->isatty(&ctx); } +static int sys_tcgetwincurpos(int fd, struct wincurpos* wcp) +{ + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + ioctx_t ctx; SetupUserIOCtx(&ctx); + return desc->tcgetwincurpos(&ctx, wcp); +} + + static int sys_tcgetwinsize(int fd, struct winsize* ws) { Ref desc = CurrentProcess()->GetDescriptor(fd); @@ -1051,6 +1061,7 @@ void Init() Syscall::Register(SYSCALL_STAT, (void*) sys_stat); Syscall::Register(SYSCALL_SYMLINKAT, (void*) sys_symlinkat); Syscall::Register(SYSCALL_TCGETPGRP, (void*) sys_tcgetpgrp); + Syscall::Register(SYSCALL_TCGETWINCURPOS, (void*) sys_tcgetwincurpos); Syscall::Register(SYSCALL_TCGETWINSIZE, (void*) sys_tcgetwinsize); Syscall::Register(SYSCALL_TCSETPGRP, (void*) sys_tcsetpgrp); Syscall::Register(SYSCALL_TRUNCATEAT, (void*) sys_truncateat); diff --git a/kernel/kernel.cpp b/kernel/kernel.cpp index 0870eb10..6b38e3cc 100644 --- a/kernel/kernel.cpp +++ b/kernel/kernel.cpp @@ -129,6 +129,11 @@ static size_t TextTermHeight(void* user) return ((TextTerminal*) user)->Height(); } +static void TextTermGetCursor(void* user, size_t* column, size_t* row) +{ + ((TextTerminal*) user)->GetCursor(column, row); +} + static bool TextTermSync(void* user) { return ((TextTerminal*) user)->Sync(); @@ -165,6 +170,11 @@ static size_t EmergencyTextTermHeight(void* user) return ((TextTerminal*) user)->EmergencyHeight(); } +static void EmergencyTextTermGetCursor(void* user, size_t* column, size_t* row) +{ + ((TextTerminal*) user)->EmergencyGetCursor(column, row); +} + static bool EmergencyTextTermSync(void* user) { return ((TextTerminal*) user)->EmergencySync(); @@ -206,6 +216,7 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo) Log::device_callback = PrintToTextTerminal; Log::device_width = TextTermWidth; Log::device_height = TextTermHeight; + Log::device_get_cursor = TextTermGetCursor; Log::device_sync = TextTermSync; Log::device_pointer = &textterm; @@ -216,6 +227,7 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo) Log::emergency_device_callback = EmergencyPrintToTextTerminal; Log::emergency_device_width = EmergencyTextTermWidth; Log::emergency_device_height = EmergencyTextTermHeight; + Log::emergency_device_get_cursor = EmergencyTextTermGetCursor; Log::emergency_device_sync = EmergencyTextTermSync; Log::emergency_device_pointer = &textterm; diff --git a/kernel/log.cpp b/kernel/log.cpp index 31d73627..3fef6ddf 100644 --- a/kernel/log.cpp +++ b/kernel/log.cpp @@ -35,6 +35,7 @@ namespace Log { size_t (*device_callback)(void*, const char*, size_t) = NULL; size_t (*device_width)(void*) = NULL; size_t (*device_height)(void*) = NULL; +void (*device_get_cursor)(void*, size_t*, size_t*) = NULL; bool (*device_sync)(void*) = NULL; void* device_pointer = NULL; bool (*emergency_device_is_impaired)(void*) = NULL; @@ -42,6 +43,7 @@ bool (*emergency_device_recoup)(void*) = NULL; void (*emergency_device_reset)(void*) = NULL; size_t (*emergency_device_callback)(void*, const char*, size_t) = NULL; size_t (*emergency_device_width)(void*) = NULL; +void (*emergency_device_get_cursor)(void*, size_t*, size_t*) = NULL; size_t (*emergency_device_height)(void*) = NULL; bool (*emergency_device_sync)(void*) = NULL; void* emergency_device_pointer = NULL; diff --git a/kernel/logterminal.cpp b/kernel/logterminal.cpp index 5c4b99b0..a8afd13e 100644 --- a/kernel/logterminal.cpp +++ b/kernel/logterminal.cpp @@ -118,6 +118,19 @@ int LogTerminal::gettermmode(ioctx_t* ctx, unsigned* mode) return 0; } +int LogTerminal::tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp) +{ + struct wincurpos retwcp; + memset(&retwcp, 0, sizeof(retwcp)); + size_t cursor_column, cursor_row; + Log::GetCursor(&cursor_column, &cursor_row); + retwcp.wcp_col = cursor_column; + retwcp.wcp_row = cursor_row; + if ( !ctx->copy_to_dest(wcp, &retwcp, sizeof(retwcp)) ) + return -1; + return 0; +} + int LogTerminal::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) { struct winsize retws; diff --git a/kernel/logterminal.h b/kernel/logterminal.h index 8abbe6dd..9afb0236 100644 --- a/kernel/logterminal.h +++ b/kernel/logterminal.h @@ -44,6 +44,7 @@ public: virtual int sync(ioctx_t* ctx); virtual ssize_t read(ioctx_t* ctx, uint8_t* buf, size_t count); virtual ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count); + virtual int tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp); virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); virtual int tcsetpgrp(ioctx_t* ctx, pid_t pgid); virtual pid_t tcgetpgrp(ioctx_t* ctx); diff --git a/kernel/panic.cpp b/kernel/panic.cpp index cb7178b9..4a3ec4e4 100644 --- a/kernel/panic.cpp +++ b/kernel/panic.cpp @@ -77,6 +77,7 @@ void PanicInit() Log::device_callback = Log::emergency_device_callback; Log::device_width = Log::emergency_device_width; Log::device_height = Log::emergency_device_height; + Log::device_get_cursor = Log::emergency_device_get_cursor; Log::device_sync = Log::emergency_device_sync; Log::device_pointer = Log::emergency_device_pointer; diff --git a/kernel/textterminal.cpp b/kernel/textterminal.cpp index fc59bc8e..f435fbe0 100644 --- a/kernel/textterminal.cpp +++ b/kernel/textterminal.cpp @@ -91,6 +91,13 @@ size_t TextTerminal::Height() const return height; } +void TextTerminal::GetCursor(size_t* column, size_t* row) const +{ + ScopedLock lock(&termlock); + *column = this->column; + *row = this->line; +} + bool TextTerminal::Sync() { // Reading something from the textbuffer may cause it to block while @@ -203,6 +210,17 @@ size_t TextTerminal::EmergencyHeight() const return height; } +void TextTerminal::EmergencyGetCursor(size_t* column, size_t* row) const +{ + // This is during a kernel emergency where preemption has been disabled and + // this is the only thread running. Another thread may have been interrupted + // while it held the terminal lock. The best case is if the terminal lock is + // currently unused, which would mean everything is safe. + + *column = this->column; + *row = this->line; +} + bool TextTerminal::EmergencySync() { // This is during a kernel emergency where preemption has been disabled and diff --git a/kernel/textterminal.h b/kernel/textterminal.h index f8eabaa5..00d01df4 100644 --- a/kernel/textterminal.h +++ b/kernel/textterminal.h @@ -40,6 +40,7 @@ public: size_t Print(const char* string, size_t stringlen); size_t Width() const; size_t Height() const; + void GetCursor(size_t* column, size_t* row) const; bool Sync(); bool EmergencyIsImpaired(); bool EmergencyRecoup(); @@ -47,6 +48,7 @@ public: size_t EmergencyPrint(const char* string, size_t stringlen); size_t EmergencyWidth() const; size_t EmergencyHeight() const; + void EmergencyGetCursor(size_t* column, size_t* row) const; bool EmergencySync(); private: diff --git a/kernel/vnode.cpp b/kernel/vnode.cpp index 929ec376..3ecc12e7 100644 --- a/kernel/vnode.cpp +++ b/kernel/vnode.cpp @@ -221,6 +221,11 @@ int Vnode::fsbind(ioctx_t* /*ctx*/, Vnode* /*node*/, int /*flags*/) return -1; } +int Vnode::tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp) +{ + return inode->tcgetwincurpos(ctx, wcp); +} + int Vnode::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) { return inode->tcgetwinsize(ctx, ws); diff --git a/libc/Makefile b/libc/Makefile index 1dc1f045..209ae054 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -435,6 +435,7 @@ sys/uio/readv.o \ sys/uio/writev.o \ sys/wait/wait.o \ sys/wait/waitpid.o \ +termios/tcgetwincurpos.o \ termios/tcgetwinsize.o \ time/clock_getres.o \ time/clock_gettime.o \ diff --git a/libc/include/fsmarshall-msg.h b/libc/include/fsmarshall-msg.h index 37626c38..6b4468ba 100644 --- a/libc/include/fsmarshall-msg.h +++ b/libc/include/fsmarshall-msg.h @@ -343,7 +343,19 @@ struct fsm_resp_tcgetpgrp pid_t pgid; }; -#define FSM_MSG_NUM 43 +#define FSM_REQ_TCGETWINCURPOS 43 +struct fsm_req_tcgetwincurpos +{ + ino_t ino; +}; + +#define FSM_RESP_TCGETWINCURPOS 44 +struct fsm_resp_tcgetwincurpos +{ + struct wincurpos pos; +}; + +#define FSM_MSG_NUM 45 #if defined(__cplusplus) } /* extern "C" */ diff --git a/libc/include/termios.h b/libc/include/termios.h index 3ea516fb..6799cd07 100644 --- a/libc/include/termios.h +++ b/libc/include/termios.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. This file is part of the Sortix C Library. @@ -24,16 +24,18 @@ /* TODO: POSIX-1.2008 compliance is only partial */ -#ifndef _TERMIOS_H -#define _TERMIOS_H 1 +#ifndef INCLUDE_TERMIOS_H +#define INCLUDE_TERMIOS_H #include #include + #include __BEGIN_DECLS +int tcgetwincurpos(int fd, struct wincurpos* wcp); int tcgetwinsize(int fd, struct winsize* ws); __END_DECLS diff --git a/libc/termios/tcgetwincurpos.cpp b/libc/termios/tcgetwincurpos.cpp new file mode 100644 index 00000000..27e829a9 --- /dev/null +++ b/libc/termios/tcgetwincurpos.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + 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 . + + termios/tcgetwincurpos.cpp + Access to terminal cursor position. + +*******************************************************************************/ + +#include + +#include + +DEFN_SYSCALL2(int, sys_tcgetwincurpos, SYSCALL_TCGETWINCURPOS, int, struct wincurpos*); + +extern "C" int tcgetwincurpos(int fd, struct wincurpos* ws) +{ + return sys_tcgetwincurpos(fd, ws); +}