diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 8fd578166ce..e460da4b90e 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -114,6 +114,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) return current->sys$set_mmap_name((void*)arg1, (size_t)arg2, (const char*)arg3); case Syscall::PosixReadlink: return current->sys$readlink((const char*)arg1, (char*)arg2, (size_t)arg3); + case Syscall::PosixTtynameR: + return current->sys$ttyname_r((int)arg1, (char*)arg2, (size_t)arg3); default: kprintf("int0x80: Unknown function %x requested {%x, %x, %x}\n", function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 7cdfecaea47..ea391edc7ca 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -37,6 +37,7 @@ enum Function { SetMmapName = 0x2005, PosixReadlink = 0x2006, PosixWrite = 0x2007, + PosixTtynameR = 0x2008, }; void initialize(); diff --git a/Kernel/TTY.h b/Kernel/TTY.h index 7b00f4ba900..76a144e6f99 100644 --- a/Kernel/TTY.h +++ b/Kernel/TTY.h @@ -13,6 +13,8 @@ public: virtual String ttyName() const = 0; protected: + virtual bool isTTY() const final { return true; } + TTY(unsigned major, unsigned minor); void emit(byte); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index f948d431e1c..5d71342500b 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -741,7 +741,7 @@ ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size) VALIDATE_USER_BUFFER(buffer, size); auto* handle = fileHandleIfExists(fd); if (!handle) - return -1; + return -EBADF; return handle->get_dir_entries((byte*)buffer, size); } @@ -749,10 +749,25 @@ int Task::sys$seek(int fd, int offset) { auto* handle = fileHandleIfExists(fd); if (!handle) - return -1; + return -EBADF; return handle->seek(offset, SEEK_SET); } +int Task::sys$ttyname_r(int fd, char* buffer, size_t size) +{ + VALIDATE_USER_BUFFER(buffer, size); + auto* handle = fileHandleIfExists(fd); + if (!handle) + return -EBADF; + if (!handle->isTTY()) + return -ENOTTY; + auto ttyName = handle->tty()->ttyName(); + if (size < ttyName.length() + 1) + return -ERANGE; + strcpy(buffer, ttyName.characters()); + return 0; +} + ssize_t Task::sys$write(int fd, const void* data, size_t size) { VALIDATE_USER_BUFFER(data, size); @@ -802,7 +817,7 @@ int Task::sys$close(int fd) { auto* handle = fileHandleIfExists(fd); if (!handle) - return -1; + return -EBADF; // FIXME: Implement. return 0; } diff --git a/Kernel/Task.h b/Kernel/Task.h index d8661c9acd4..15536385b98 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -111,6 +111,7 @@ public: int sys$get_arguments(int* argc, char*** argv); int sys$uname(utsname*); int sys$readlink(const char*, char*, size_t); + int sys$ttyname_r(int fd, char*, size_t); static void initialize(); diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 75c543259d4..271c4347fa2 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -38,6 +38,20 @@ ssize_t write(int fd, const void* buf, size_t count) __RETURN_WITH_ERRNO(rc, rc, -1); } +int ttyname_r(int fd, char* buffer, size_t size) +{ + int rc = Syscall::invoke(Syscall::PosixTtynameR, (dword)fd, (dword)buffer, (dword)size); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +static char ttyname_buf[32]; +char* ttyname(int fd) +{ + if (ttyname_r(fd, ttyname_buf, sizeof(ttyname_buf)) < 0) + return nullptr; + return ttyname_buf; +} + int close(int fd) { int rc = Syscall::invoke(Syscall::PosixClose, fd); diff --git a/LibC/unistd.h b/LibC/unistd.h index ed78603d970..25ac8e05869 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -18,6 +18,8 @@ int lstat(const char* path, stat* statbuf); int sleep(unsigned seconds); int gethostname(char*, size_t); ssize_t readlink(const char* path, char* buffer, size_t); +char* ttyname(int fd); +int ttyname_r(int fd, char* buffer, size_t); #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) #define WTERMSIG(status) ((status) & 0x7f) diff --git a/Userland/sh.cpp b/Userland/sh.cpp index 069cd48594a..523a41119b9 100644 --- a/Userland/sh.cpp +++ b/Userland/sh.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include struct GlobalState { @@ -148,6 +149,17 @@ static int runcmd(char* cmd) return retval; } +static void greeting() +{ + utsname uts; + int rc = uname(&uts); + if (rc < 0) { + perror("uname"); + return; + } + printf("\n%s/%s on %s\n\n", uts.sysname, uts.machine, ttyname(0)); +} + int main(int, char**) { g = new GlobalState; @@ -155,6 +167,8 @@ int main(int, char**) if (rc < 0) perror("gethostname"); + greeting(); + char linebuf[128]; int linedx = 0; linebuf[0] = '\0'; diff --git a/VirtualFileSystem/CharacterDevice.h b/VirtualFileSystem/CharacterDevice.h index c67ea471a1e..a8bcaf99331 100644 --- a/VirtualFileSystem/CharacterDevice.h +++ b/VirtualFileSystem/CharacterDevice.h @@ -18,6 +18,8 @@ public: unsigned major() const { return m_major; } unsigned minor() const { return m_minor; } + virtual bool isTTY() const { return false; } + protected: CharacterDevice(unsigned major, unsigned minor) : m_major(major), m_minor(minor) { } diff --git a/VirtualFileSystem/FileHandle.cpp b/VirtualFileSystem/FileHandle.cpp index d68ef5343b8..c114c2469eb 100644 --- a/VirtualFileSystem/FileHandle.cpp +++ b/VirtualFileSystem/FileHandle.cpp @@ -3,6 +3,7 @@ #include "CharacterDevice.h" #include "sys-errno.h" #include "UnixTypes.h" +#include "TTY.h" #include FileHandle::FileHandle(RetainPtr&& vnode) @@ -109,6 +110,7 @@ Unix::ssize_t FileHandle::write(const byte* data, Unix::size_t size) } // FIXME: Implement non-device writes. ASSERT_NOT_REACHED(); + return -1; } bool FileHandle::hasDataAvailableForRead() @@ -160,3 +162,17 @@ ssize_t FileHandle::get_dir_entries(byte* buffer, Unix::size_t size) memcpy(buffer, tempBuffer.pointer(), stream.offset()); return stream.offset(); } + +bool FileHandle::isTTY() const +{ + if (auto* device = m_vnode->characterDevice()) + return device->isTTY(); + return false; +} + +const TTY* FileHandle::tty() const +{ + if (auto* device = m_vnode->characterDevice()) + return static_cast(device); + return nullptr; +} diff --git a/VirtualFileSystem/FileHandle.h b/VirtualFileSystem/FileHandle.h index e442bf12248..e31cebf63b5 100644 --- a/VirtualFileSystem/FileHandle.h +++ b/VirtualFileSystem/FileHandle.h @@ -4,6 +4,8 @@ #include "InodeMetadata.h" #include +class TTY; + class FileHandle { public: explicit FileHandle(RetainPtr&&); @@ -24,6 +26,9 @@ public: bool isDirectory() const; + bool isTTY() const; + const TTY* tty() const; + InodeMetadata metadata() const { return m_vnode->metadata(); } VirtualFileSystem::Node* vnode() { return m_vnode.ptr(); } diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index 34f6d9ad087..07a8d9a442b 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -55,6 +55,7 @@ public: bool isCharacterDevice() const { return m_characterDevice; } CharacterDevice* characterDevice() { return m_characterDevice; } + const CharacterDevice* characterDevice() const { return m_characterDevice; } void retain(); void release();