Sfoglia il codice sorgente

feat(syscall): uname, getpgid, getuid, rt_sigaction(half works)

greatbridf 1 anno fa
parent
commit
5926e83a34

+ 1 - 0
CMakeLists.txt

@@ -68,6 +68,7 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         include/kernel/mem.h
                         include/kernel/mm.hpp
                         include/kernel/module.hpp
+                        include/kernel/utsname.hpp
                         include/kernel/vfs.hpp
                         include/kernel/vga.hpp
                         include/kernel/signal.hpp

+ 1 - 0
gblibc/include/errno.h

@@ -19,6 +19,7 @@ extern int* __errno_location(void);
 #define ECHILD 10
 #define ENOMEM 12
 #define EACCES 13
+#define EFAULT 14
 #define EEXIST 17
 #define ENOTDIR 20
 #define EISDIR 21

+ 3 - 0
gblibc/include/fcntl.h

@@ -16,6 +16,9 @@
 #define F_DUPFD 0
 #define F_GETFD 1
 #define F_SETFD 2
+#define F_GETFL 3
+#define F_SETFL 4
+#define F_DUPFD_CLOEXEC 1030
 // TODO: more flags
 
 #define FD_CLOEXEC 1

+ 7 - 4
gblibc/include/signal.h

@@ -41,15 +41,18 @@ extern "C" {
 #define SIGPWR    30
 #define SIGSYS    31
 #define SIGUNUSED SIGSYS
+#define SIGRTMIN  32
+#define SIGRTMAX  64
 
 #define SIG_BLOCK 0
 #define SIG_UNBLOCK 1
 #define SIG_SETMASK 2
 
-typedef void (*sig_t)(int);
-typedef struct sigset_t {
-    unsigned char __sig[8];
-} sigset_t;
+#define SIG_DFL ((sighandler_t)0)
+#define SIG_IGN ((sighandler_t)1)
+
+typedef void (*sighandler_t)(int);
+typedef void (*sigrestorer_t)(void);
 
 int kill(pid_t pid, int sig);
 int raise(int sig);

+ 43 - 0
gblibc/include/sys/utsname.h

@@ -0,0 +1,43 @@
+#ifndef __GBLIBC_SYS_UTSNAME_H
+#define __GBLIBC_SYS_UTSNAME_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define OLD_UTSNAME_LENGTH 8
+
+struct oldold_utsname {
+    char sysname[9];
+    char nodename[9];
+    char release[9];
+    char version[9];
+    char machine[9];
+};
+
+#define UTSNAME_LENGTH 64
+
+struct old_utsname {
+    char sysname[65];
+    char nodename[65];
+    char release[65];
+    char version[65];
+    char machine[65];
+};
+
+struct new_utsname {
+    char sysname[65];
+    char nodename[65];
+    char release[65];
+    char version[65];
+    char machine[65];
+    char domainname[65];
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 34 - 54
include/kernel/process.hpp

@@ -92,11 +92,12 @@ public:
 
     constexpr void sleep()
     { attr.ready = 0; }
-    constexpr void wakeup()
-    { attr.ready = 1; }
+    void wakeup();
     constexpr bool is_ready() const
     { return attr.ready; }
 
+    void send_signal(kernel::signal_list::signo_type signal);
+
     constexpr thread(thread&& val) = default;
     inline ~thread() { free_kstack(pkstack); }
 
@@ -111,65 +112,46 @@ public:
 }
 
 class filearr {
-public:
-    using array_type = std::map<int, std::shared_ptr<fs::file>>;
-
 private:
-    array_type arr;
-    std::priority_queue<int, std::vector<int>, std::greater<int>> _fds;
-    int _greatest_fd;
+    // TODO: change this
+    struct fditem {
+        int flags;
+        std::shared_ptr<fs::file> file;
+    };
+
+    std::map<int, fditem> arr;
+    int min_avail { };
 
 private:
-    constexpr int next_fd()
-    {
-        if (_fds.empty())
-            return _greatest_fd++;
-        int retval = _fds.top();
-        _fds.pop();
-        return retval;
-    }
+    int allocate_fd(int from);
+    void release_fd(int fd);
+    inline int next_fd() { return allocate_fd(min_avail); }
 
 public:
-    constexpr filearr(const filearr&) = delete;
-    constexpr filearr& operator=(const filearr&) = delete;
-    constexpr filearr& operator=(filearr&&) = delete;
-    constexpr filearr(void) = default;
+    constexpr filearr() = default;
+    constexpr filearr(const filearr& val) = default;
     constexpr filearr(filearr&& val) = default;
 
-    constexpr int dup(int old_fd)
-    {
-        return dup2(old_fd, next_fd());
-    }
+    constexpr filearr& operator=(const filearr&) = delete;
+    constexpr filearr& operator=(filearr&&) = delete;
 
     // TODO: the third parameter should be int flags
     //       determining whether the fd should be closed
     //       after exec() (FD_CLOEXEC)
-    constexpr int dup2(int old_fd, int new_fd)
-    {
-        close(new_fd);
+    int dup2(int old_fd, int new_fd);
+    int dup(int old_fd);
 
-        auto iter = arr.find(old_fd);
-        if (!iter)
-            return -EBADF;
+    int dupfd(int fd, int minfd, int flags);
 
-        this->arr.emplace(new_fd, iter->second);
-        return new_fd;
-    }
-
-    constexpr void dup_all(const filearr& orig)
-    {
-        this->_fds = orig._fds;
-        this->_greatest_fd = orig._greatest_fd;
-        for (auto [ fd, fp ] : orig.arr)
-            this->arr.emplace(fd, fp);
-    }
+    int set_flags(int fd, int flags);
+    int clear_flags(int fd, int flags);
 
     constexpr fs::file* operator[](int i) const
     {
         auto iter = arr.find(i);
         if (!iter)
             return nullptr;
-        return iter->second.get();
+        return iter->second.file.get();
     }
 
     int pipe(int pipefd[2])
@@ -178,28 +160,26 @@ public:
 
         bool inserted = false;
         int fd = next_fd();
-        std::tie(std::ignore, inserted) = arr.emplace(fd,
-            std::shared_ptr<fs::file> {
+        std::tie(std::ignore, inserted) = arr.emplace(fd, fditem {
+            0, std::shared_ptr<fs::file> {
                 new fs::fifo_file(nullptr, {
                     .read = 1,
                     .write = 0,
-                    .close_on_exec = 0,
                 }, ppipe),
-        });
+        } } );
         assert(inserted);
 
         // TODO: use copy_to_user()
         pipefd[0] = fd;
 
         fd = next_fd();
-        std::tie(std::ignore, inserted) = arr.emplace(fd,
-            std::shared_ptr<fs::file> {
+        std::tie(std::ignore, inserted) = arr.emplace(fd, fditem {
+            0, std::shared_ptr<fs::file> {
                 new fs::fifo_file(nullptr, {
                     .read = 0,
                     .write = 1,
-                    .close_on_exec = 0,
                 }, ppipe),
-        });
+        } } );
         assert(inserted);
 
         // TODO: use copy_to_user()
@@ -216,18 +196,18 @@ public:
         if (!iter)
             return;
 
-        _fds.push(fd);
+        release_fd(fd);
         arr.erase(iter);
     }
 
     constexpr void onexec()
     {
         for (auto iter = arr.begin(); iter != arr.end(); ) {
-            if (!iter->second->flags.close_on_exec) {
+            if (!(iter->second.flags & O_CLOEXEC)) {
                 ++iter;
                 continue;
             }
-            _fds.push(iter->first);
+            release_fd(iter->first);
             iter = arr.erase(iter);
         }
     }
@@ -235,7 +215,7 @@ public:
     constexpr void close_all(void)
     {
         for (const auto& item : arr)
-            _fds.push(item.first);
+            release_fd(item.first);
         arr.clear();
     }
 

+ 22 - 8
include/kernel/signal.hpp

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <map>
 #include <list>
 
 #include <signal.h>
@@ -10,6 +11,15 @@
 
 namespace kernel {
 
+using sigmask_type = uint64_t;
+
+struct sigaction {
+    sighandler_t sa_handler;
+    unsigned long sa_flags;
+    sigrestorer_t sa_restorer;
+    sigmask_type sa_mask;
+};
+
 class signal_list {
 public:
     using signo_type = uint32_t;
@@ -17,29 +27,33 @@ public:
 
 private:
     list_type m_list;
-    signo_type m_mask;
-    sig_t m_handlers[32];
+    sigmask_type m_mask { };
+    std::map<signo_type, sigaction> m_handlers;
 
 public:
     static constexpr bool check_valid(signo_type sig)
     {
-        return sig > 0 && sig < 32;
+        return sig >= 1 && sig <= 64;
     }
 
 public:
-    signal_list();
+    constexpr signal_list() = default;
     constexpr signal_list(const signal_list& val) = default;
     constexpr signal_list(signal_list&& val) = default;
 
     void on_exec();
 
-    void get_mask(sigset_t* __user mask) const;
-    void set_mask(const sigset_t* __user mask);
+    sigmask_type get_mask() const;
+    void set_mask(sigmask_type mask);
+    void mask(sigmask_type mask);
+    void unmask(sigmask_type mask);
+
+    void set_handler(signo_type signal, const sigaction& action);
+    void get_handler(signo_type signal, sigaction& action) const;
 
-    constexpr bool is_masked(signo_type signal) const { return m_mask & (1 << signal); }
     constexpr bool empty(void) const { return m_list.empty(); }
 
-    void set(signo_type signal);
+    void raise(signo_type signal);
     signo_type handle();
     void after_signal(signo_type signal);
 };

+ 9 - 0
include/kernel/utsname.hpp

@@ -0,0 +1,9 @@
+#pragma once
+
+#include <sys/utsname.h>
+
+namespace kernel {
+
+inline new_utsname* sys_utsname;
+
+} // namespace kernel

+ 0 - 1
include/kernel/vfs.hpp

@@ -270,7 +270,6 @@ struct file {
     struct file_flags {
         uint32_t read : 1;
         uint32_t write : 1;
-        uint32_t close_on_exec : 1;
     } flags {};
 
     file(mode_t mode, vfs::dentry* parent, file_flags flags)

+ 1 - 4
src/kernel/event/event.cpp

@@ -69,7 +69,6 @@ void kernel::cond_var::notify(void)
 
     auto* thd = *iter;
     thd->wakeup();
-    readythds->push(thd);
 
     m_subscribers.erase(iter);
 }
@@ -78,10 +77,8 @@ void kernel::cond_var::notify_all(void)
 {
     types::lock_guard lck(m_mtx);
 
-    for (auto& thd : m_subscribers) {
+    for (auto& thd : m_subscribers)
         thd->wakeup();
-        readythds->push(thd);
-    }
 
     m_subscribers.clear();
 }

+ 109 - 24
src/kernel/process.cpp

@@ -94,6 +94,85 @@ void kernel::tasks::thread::free_kstack(uint32_t p)
     pkstack_bmp->clear(p);
 }
 
+int filearr::allocate_fd(int from)
+{
+    if (from < min_avail)
+        from = min_avail;
+
+    if (from == min_avail) {
+        int nextfd = min_avail + 1;
+        auto iter = arr.find(nextfd);
+        while (iter != arr.end() && nextfd == iter->first)
+            ++nextfd, ++iter;
+
+        int retval = min_avail;
+        min_avail = nextfd;
+        return retval;
+    }
+
+    int fd = from;
+    auto iter = arr.find(fd);
+    while (iter != arr.end() && fd == iter->first)
+        ++fd, ++iter;
+
+    return fd;
+}
+
+void filearr::release_fd(int fd)
+{
+    if (fd < min_avail)
+        min_avail = fd;
+}
+
+int filearr::dup(int old_fd)
+{
+    return dup2(old_fd, next_fd());
+}
+
+int filearr::dup2(int old_fd, int new_fd)
+{
+    close(new_fd);
+
+    auto iter = arr.find(old_fd);
+    if (!iter)
+        return -EBADF;
+
+    this->arr.emplace(new_fd, iter->second);
+    return new_fd;
+}
+
+int filearr::dupfd(int fd, int minfd, int flags)
+{
+    auto iter = arr.find(fd);
+    if (!iter)
+        return -EBADF;
+
+    int new_fd = allocate_fd(minfd);
+    auto [ newiter, inserted ] = arr.emplace(new_fd, iter->second);
+    assert(inserted);
+
+    newiter->second.flags = flags;
+    return new_fd;
+}
+
+int filearr::set_flags(int fd, int flags)
+{
+    auto iter = arr.find(fd);
+    if (!iter)
+        return -EBADF;
+    iter->second.flags |= flags;
+    return 0;
+}
+
+int filearr::clear_flags(int fd, int flags)
+{
+    auto iter = arr.find(fd);
+    if (!iter)
+        return -EBADF;
+    iter->second.flags &= ~flags;
+    return 0;
+}
+
 // TODO: file opening permissions check
 int filearr::open(const process &current,
     const types::path& filepath, int flags, mode_t mode)
@@ -139,41 +218,47 @@ int filearr::open(const process &current,
     }
 
     int fd = next_fd();
-    auto [ _, inserted ] = arr.emplace(fd, std::shared_ptr<fs::file> {
-        new fs::regular_file(dentry->parent, {
-            .read = !(flags & O_WRONLY),
-            .write = !!(flags & (O_WRONLY | O_RDWR)),
-            .close_on_exec = !!(flags & O_CLOEXEC),
-            }, 0, dentry->ind
-        )
-    });
+    auto [ _, inserted ] = arr.emplace(fd, fditem {
+        flags, std::shared_ptr<fs::file> {
+            new fs::regular_file(dentry->parent, {
+                .read = !(flags & O_WRONLY),
+                .write = !!(flags & (O_WRONLY | O_RDWR)),
+            }, 0, dentry->ind),
+    } } );
     assert(inserted);
     return fd;
 }
 
 process::process(const process& parent, pid_t pid)
-    : mms { parent.mms }, attr { parent.attr } , pwd { parent.pwd }
-    , umask { parent.umask }, pid { pid } , ppid { parent.pid }
-    , pgid { parent.pgid } , sid { parent.sid }
-    , control_tty { parent.control_tty }, root { parent.root }
-{
-    this->files.dup_all(parent.files);
-}
+    : mms { parent.mms }, attr { parent.attr } , files { parent.files }
+    , pwd { parent.pwd }, umask { parent.umask }, pid { pid }
+    , ppid { parent.pid }, pgid { parent.pgid } , sid { parent.sid }
+    , control_tty { parent.control_tty }, root { parent.root } { }
 
 process::process(pid_t pid, pid_t ppid)
     : attr { .system = true }
     , pwd { "/" } , pid { pid } , ppid { ppid } { }
 
-void process::send_signal(kernel::signal_list::signo_type signal)
+using kernel::tasks::thread;
+using signo_type = kernel::signal_list::signo_type;
+
+void process::send_signal(signo_type signal)
 {
-    for (auto& thd : thds) {
-        if (thd.signals.is_masked(signal))
-            continue;
-        thd.signals.set(signal);
-        thd.wakeup();
-        readythds->push(&thd);
-        break;
-    }
+    for (auto& thd : thds)
+        thd.send_signal(signal);
+}
+
+void thread::wakeup()
+{
+    attr.ready = 1;
+    readythds->push(this);
+}
+
+void thread::send_signal(signo_type signal)
+{
+    if (signal == SIGCONT)
+        this->wakeup();
+    signals.raise(signal);
 }
 
 void proclist::kill(pid_t pid, int exit_code)

+ 94 - 76
src/kernel/signal.cpp

@@ -3,16 +3,35 @@
 
 #include <signal.h>
 
+#define sigmask(sig) (1ULL << ((sig)-1))
+
+#define sigmask_now (sigmask(SIGKILL) | sigmask(SIGSTOP))
+
+#define sigmask_ignore (sigmask(SIGCHLD) | sigmask(SIGURG) | sigmask(SIGWINCH))
+
+#define sigmask_coredump (\
+    sigmask(SIGQUIT) | sigmask(SIGILL) | sigmask(SIGTRAP) | sigmask(SIGABRT) | \
+    sigmask(SIGFPE) | sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGSYS) | \
+    sigmask(SIGXCPU) | sigmask(SIGXFSZ) )
+
+#define sigmask_stop (\
+    sigmask(SIGSTOP) | sigmask(SIGTSTP) | sigmask(SIGTTIN) | sigmask(SIGTTOU))
+
 using kernel::signal_list;
 using signo_type = signal_list::signo_type;
 
-static void continue_process(int) { }
+static void continue_process(int signal)
+{
+    current_thread->signals.after_signal(signal);
+}
 
-static void stop_process(int)
+static void stop_process(int signal)
 {
     current_thread->sleep();
 
     schedule();
+
+    current_thread->signals.after_signal(signal);
 }
 
 static void terminate_process(int signo)
@@ -25,65 +44,62 @@ static void terminate_process_with_core_dump(int signo)
     terminate_process(signo & 0x80);
 }
 
-static sig_t default_handlers[32] = {
-    nullptr,
-    terminate_process, // SIGHUP
-    terminate_process, // SIGINT
-    terminate_process_with_core_dump, // SIGQUIT
-    terminate_process_with_core_dump, // SIGILL
-    terminate_process_with_core_dump, // SIGTRAP
-    terminate_process_with_core_dump, // SIGABRT, SIGIOT
-    terminate_process_with_core_dump, // SIGBUS
-    terminate_process_with_core_dump, // SIGFPE
-    terminate_process, // SIGKILL
-    terminate_process, // SIGUSR1
-    terminate_process_with_core_dump, // SIGSEGV
-    terminate_process, // SIGUSR2
-    terminate_process, // SIGPIPE
-    terminate_process, // SIGALRM
-    terminate_process, // SIGTERM
-    terminate_process, // SIGSTKFLT
-    nullptr, // SIGCHLD
-    continue_process, // SIGCONT
-    stop_process, // SIGSTOP
-    stop_process, // SIGTSTP
-    stop_process, // SIGTTIN
-    stop_process, // SIGTTOU
-    nullptr, // SIGURG
-    terminate_process_with_core_dump, // SIGXCPU
-    terminate_process_with_core_dump, // SIGXFSZ
-    terminate_process, // SIGVTALRM
-    terminate_process, // SIGPROF
-    nullptr, // SIGWINCH
-    terminate_process, // SIGIO, SIGPOLL
-    terminate_process, // SIGPWR
-    terminate_process_with_core_dump, // SIGSYS, SIGUNUSED
-};
-
-signal_list::signal_list()
-    : m_mask(0)
+void signal_list::set_handler(signo_type signal, const sigaction& action)
 {
-    memcpy(m_handlers, default_handlers, sizeof(m_handlers));
+    if (action.sa_handler == SIG_DFL) {
+        m_handlers.erase(signal);
+        return;
+    }
+    else {
+        m_handlers[signal] = action;
+    }
 }
 
-void signal_list::on_exec()
+void signal_list::get_handler(signo_type signal, sigaction& action) const
 {
-    for (int i = 1; i < 32; ++i) {
-        if (m_handlers[i])
-            m_handlers[i] = default_handlers[i];
+    auto iter = m_handlers.find(signal);
+    if (iter == m_handlers.end()) {
+        action.sa_handler = SIG_DFL;
+        action.sa_flags = 0;
+        action.sa_restorer = nullptr;
+        action.sa_mask = 0;
+    }
+    else {
+        action = iter->second;
     }
 }
 
-void signal_list::set(signo_type signal)
+void signal_list::on_exec()
 {
-    if (m_mask & (1 << signal))
-        return;
+    std::erase_if(m_handlers, [](auto& pair) {
+        return pair.second.sa_handler != SIG_IGN;
+    });
+}
 
-    if (!m_handlers[signal])
+void signal_list::raise(signo_type signal)
+{
+    // TODO: clear pending signals
+    // if (signal == SIGCONT) {
+    //     m_list.remove_if([](signo_type sig) {
+    //         return sig == SIGSTOP || sig == SIGTSTP
+    //             || sig == SIGTTIN || sig == SIGTTOU;
+    //     });
+    // }
+
+    // if (signal == SIGSTOP)
+    //     m_list.remove(SIGCONT);
+
+    if (m_mask & sigmask(signal))
         return;
 
+    auto iter = m_handlers.find(signal);
+    if (iter != m_handlers.end()) {
+        if (iter->second.sa_handler == SIG_IGN)
+            return;
+    }
+
     m_list.push_back(signal);
-    m_mask |= (1 << signal);
+    m_mask |= sigmask(signal);
 }
 
 signo_type signal_list::handle()
@@ -94,39 +110,41 @@ signo_type signal_list::handle()
     auto signal = m_list.front();
     m_list.pop_front();
 
-    if (!m_handlers[signal])
-        return 0;
+    // default handlers
+    if (sigmask(signal) & sigmask_now) {
+        if (signal == SIGKILL)
+            terminate_process(signal);
+        else // SIGSTOP
+            stop_process(signal);
+        return signal;
+    }
 
-    m_handlers[signal](signal);
+    auto iter = m_handlers.find(signal);
+    if (iter == m_handlers.end()) {
+        if (signal == SIGCONT)
+            continue_process(signal);
+        else if (sigmask(signal) & sigmask_stop)
+            stop_process(signal);
+        else if (sigmask(signal) & sigmask_coredump)
+            terminate_process_with_core_dump(signal);
+        else if (!(sigmask(signal) & sigmask_ignore))
+            terminate_process(signal);
+        else // signal is ignored by default
+            return 0;
+    }
+    else {
+        iter->second.sa_handler(signal);
+    }
 
     return signal;
 }
 
 void signal_list::after_signal(signo_type signal)
 {
-    this->m_mask &= ~(1 << signal);
+    this->m_mask &= ~sigmask(signal);
 }
 
-void signal_list::get_mask(sigset_t* mask) const
-{
-    if (!mask)
-        return;
-
-    memset(mask, 0x00, sizeof(sigset_t));
-    for (int i = 1; i < 32; ++i) {
-        if (is_masked(i))
-            mask->__sig[(i-1)/4] |= 3 << (i-1) % 4 * 2;
-    }
-}
-
-void signal_list::set_mask(const sigset_t* mask)
-{
-    if (!mask)
-        return;
-
-    m_mask = 0;
-    for (int i = 1; i < 32; ++i) {
-        if (mask->__sig[(i-1)/4] & (3 << (i-1) % 4 * 2))
-            m_mask |= (1 << i);
-    }
-}
+kernel::sigmask_type signal_list::get_mask() const { return m_mask; }
+void signal_list::set_mask(sigmask_type mask) { m_mask = mask & ~sigmask_now; }
+void signal_list::mask(sigmask_type mask) { set_mask(m_mask | mask); }
+void signal_list::unmask(sigmask_type mask) { set_mask(m_mask & ~mask); }

+ 105 - 33
src/kernel/syscall.cpp

@@ -13,6 +13,7 @@
 #include <sys/prctl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/utsname.h>
 
 #include <kernel/user/thread_local.hpp>
 #include <kernel/interrupt.h>
@@ -23,6 +24,7 @@
 #include <kernel/signal.hpp>
 #include <kernel/syscall.hpp>
 #include <kernel/tty.hpp>
+#include <kernel/utsname.hpp>
 #include <kernel/vfs.hpp>
 #include <kernel/hw/timer.h>
 
@@ -47,6 +49,12 @@
 #define SYSCALL_HANDLERS_SIZE (404)
 syscall_handler syscall_handlers[SYSCALL_HANDLERS_SIZE];
 
+static void not_implemented()
+{
+    console->print("\n[kernel] this function is not implemented\n");
+    current_thread->send_signal(SIGSYS);
+}
+
 extern "C" void _syscall_stub_fork_return(void);
 int _syscall_fork(interrupt_stack* data)
 {
@@ -397,6 +405,7 @@ int _syscall_ioctl(interrupt_stack* data)
         break;
     }
     default:
+        not_implemented();
         return -EINVAL;
     }
 
@@ -493,7 +502,12 @@ int _syscall_clock_gettime64(interrupt_stack* data)
 
 int _syscall_getuid(interrupt_stack*)
 {
-    return 0; // all user is root for now
+    return 0; // all user are root for now
+}
+
+int _syscall_geteuid(interrupt_stack*)
+{
+    return 0; // all user are root for now
 }
 
 int _syscall_brk(interrupt_stack* data)
@@ -568,12 +582,6 @@ int _syscall_munmap(interrupt_stack* data)
     return current_process->mms.unmap(addr, len, false);
 }
 
-[[noreturn]] static void not_implemented()
-{
-    console->print("\n[kernel] this function is not implemented\n");
-    kill_current(SIGSYS);
-}
-
 int _syscall_sendfile64(interrupt_stack* data)
 {
     SYSCALL_ARG1(int, out_fd);
@@ -591,8 +599,10 @@ int _syscall_sendfile64(interrupt_stack* data)
     if (!S_ISREG(in_file->mode) && !S_ISBLK(in_file->mode))
         return -EINVAL;
 
-    if (offset)
+    if (offset) {
         not_implemented();
+        return -EINVAL;
+    }
 
     constexpr size_t bufsize = 512;
     std::vector<char> buf(bufsize);
@@ -622,11 +632,15 @@ int _syscall_statx(interrupt_stack* data)
     SYSCALL_ARG5(statx* __user, statxbuf);
 
     // AT_STATX_SYNC_AS_STAT is the default value
-    if (flags != AT_STATX_SYNC_AS_STAT && !(flags & AT_SYMLINK_NOFOLLOW))
+    if (flags != AT_STATX_SYNC_AS_STAT && !(flags & AT_SYMLINK_NOFOLLOW)) {
         not_implemented();
+        return -EINVAL;
+    }
 
-    if (dirfd != AT_FDCWD)
+    if (dirfd != AT_FDCWD) {
         not_implemented();
+        return -EINVAL;
+    }
 
     auto* dent = fs::vfs_open(*current_process->root,
         types::make_path(path, current_process->pwd));
@@ -652,8 +666,13 @@ int _syscall_fcntl64(interrupt_stack* data)
 
     switch (cmd) {
     case F_SETFD:
-        file->flags.close_on_exec = !!(arg & FD_CLOEXEC);
-        return 0;
+        return current_process->files.set_flags(
+            fd, (arg & FD_CLOEXEC) ? O_CLOEXEC : 0);
+    case F_DUPFD:
+    case F_DUPFD_CLOEXEC: {
+        int flag = (cmd & F_DUPFD_CLOEXEC) ? O_CLOEXEC : 0;
+        return current_process->files.dupfd(fd, arg, flag);
+    }
     default:
         not_implemented();
         return -EINVAL;
@@ -753,48 +772,96 @@ int _syscall_kill(interrupt_stack* data)
 
 int _syscall_rt_sigprocmask(interrupt_stack* data)
 {
+    using kernel::sigmask_type;
+
     SYSCALL_ARG1(int, how);
-    SYSCALL_ARG2(const sigset_t* __user, set);
-    SYSCALL_ARG3(sigset_t* __user, oldset);
+    SYSCALL_ARG2(const sigmask_type* __user, set);
+    SYSCALL_ARG3(sigmask_type* __user, oldset);
     SYSCALL_ARG4(size_t, sigsetsize);
 
-    if (sigsetsize != sizeof(sigset_t))
+    if (sigsetsize != sizeof(sigmask_type))
         return -EINVAL;
 
-    sigset_t sigs;
-    current_thread->signals.get_mask(&sigs);
+    sigmask_type sigs = current_thread->signals.get_mask();
 
     // TODO: use copy_to_user
     if (oldset)
-        memcpy(oldset, &sigs, sizeof(sigset_t));
+        memcpy(oldset, &sigs, sizeof(sigmask_type));
+
+    if (!set)
+        return 0;
 
     // TODO: use copy_from_user
     switch (how) {
     case SIG_BLOCK:
-        if (!set)
-            break;
-
-        for (size_t i = 0; i < sizeof(sigset_t); ++i)
-            sigs.__sig[i] |= set->__sig[i];
-        current_thread->signals.set_mask(&sigs);
+        current_thread->signals.mask(*set);
         break;
     case SIG_UNBLOCK:
-        if (!set)
-            break;
-
-        for (size_t i = 0; i < sizeof(sigset_t); ++i)
-            sigs.__sig[i] &= ~set->__sig[i];
-        current_thread->signals.set_mask(&sigs);
+        current_thread->signals.set_mask(*set);
         break;
     case SIG_SETMASK:
-        if (set)
-            current_thread->signals.set_mask(set);
+        current_thread->signals.set_mask(*set);
         break;
     }
 
     return 0;
 }
 
+int _syscall_rt_sigaction(interrupt_stack* data)
+{
+    using kernel::sigaction;
+    using kernel::sigmask_type;
+    SYSCALL_ARG1(int, signum);
+    SYSCALL_ARG2(const sigaction* __user, act);
+    SYSCALL_ARG3(sigaction* __user, oldact);
+    SYSCALL_ARG4(size_t, sigsetsize);
+
+    if (sigsetsize != sizeof(sigmask_type))
+        return -EINVAL;
+
+    if (!kernel::signal_list::check_valid(signum)
+        || signum == SIGKILL || signum == SIGSTOP)
+        return -EINVAL;
+
+    // TODO: use copy_to_user
+    if (oldact)
+        current_thread->signals.get_handler(signum, *oldact);
+
+    if (!act)
+        return 0;
+
+    // TODO: use copy_from_user
+    current_thread->signals.set_handler(signum, *act);
+
+    return 0;
+}
+
+int _syscall_newuname(interrupt_stack* data)
+{
+    SYSCALL_ARG1(new_utsname* __user, buf);
+
+    if (!buf)
+        return -EFAULT;
+
+    // TODO: use copy_to_user
+    memcpy(buf, kernel::sys_utsname, sizeof(new_utsname));
+
+    return 0;
+}
+
+pid_t _syscall_getpgid(interrupt_stack* data)
+{
+    SYSCALL_ARG1(pid_t, pid);
+
+    if (pid == 0)
+        return current_process->pgid;
+
+    if (!procs->try_find(pid))
+        return -ESRCH;
+
+    return procs->find(pid).pgid;
+}
+
 extern "C" void syscall_entry(interrupt_stack* data)
 {
     int syscall_no = SYSCALL_NO;
@@ -806,6 +873,7 @@ extern "C" void syscall_entry(interrupt_stack* data)
             "[kernel] syscall %x not implemented\n", syscall_no);
         console->print(buf);
         not_implemented();
+        return;
     }
 
     int ret = syscall_handlers[syscall_no](data);
@@ -842,14 +910,18 @@ void init_syscall(void)
     syscall_handlers[0x42] = _syscall_setsid;
     syscall_handlers[0x4e] = _syscall_gettimeofday;
     syscall_handlers[0x5b] = _syscall_munmap;
-    syscall_handlers[0x84] = _syscall_getdents;
+    syscall_handlers[0x7a] = _syscall_newuname;
+    syscall_handlers[0x84] = _syscall_getpgid;
+    syscall_handlers[0x8d] = _syscall_getdents;
     syscall_handlers[0x92] = _syscall_writev;
     syscall_handlers[0x93] = _syscall_getsid;
     syscall_handlers[0xac] = _syscall_prctl;
+    syscall_handlers[0xae] = _syscall_rt_sigaction;
     syscall_handlers[0xaf] = _syscall_rt_sigprocmask;
     syscall_handlers[0xb7] = _syscall_getcwd;
     syscall_handlers[0xc0] = _syscall_mmap_pgoff;
     syscall_handlers[0xc7] = _syscall_getuid;
+    syscall_handlers[0xc9] = _syscall_geteuid;
     syscall_handlers[0xdc] = _syscall_getdents64;
     syscall_handlers[0xdd] = _syscall_fcntl64;
     syscall_handlers[0xef] = _syscall_sendfile64;

+ 2 - 2
src/kernel/vfs.cpp

@@ -883,7 +883,7 @@ int fs::pipe::write(const char* buf, size_t n)
         types::lock_guard lck(mtx);
 
         if (!is_readable()) {
-            current_thread->signals.set(SIGPIPE);
+            current_thread->signals.raise(SIGPIPE);
             return -EPIPE;
         }
 
@@ -892,7 +892,7 @@ int fs::pipe::write(const char* buf, size_t n)
                 return -EINTR;
 
             if (!is_readable()) {
-                current_thread->signals.set(SIGPIPE);
+                current_thread->signals.raise(SIGPIPE);
                 return -EPIPE;
             }
         }

+ 27 - 4
src/kinit.cpp

@@ -1,6 +1,14 @@
 #include <asm/port_io.h>
 #include <asm/sys.h>
+
 #include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/utsname.h>
+
+#include <types/status.h>
+#include <types/types.h>
+
 #include <kernel/event/event.h>
 #include <kernel/hw/keyboard.h>
 #include <kernel/hw/pci.hpp>
@@ -13,11 +21,8 @@
 #include <kernel/syscall.hpp>
 #include <kernel/task.h>
 #include <kernel/tty.hpp>
+#include <kernel/utsname.hpp>
 #include <kernel/vga.hpp>
-#include <stdint.h>
-#include <stdio.h>
-#include <types/status.h>
-#include <types/types.h>
 
 typedef void (*constructor)(void);
 extern constructor const SECTION(".rodata.kinit") start_ctors;
@@ -84,6 +89,22 @@ static inline int init_console(const char* name)
 
 extern void init_vfs();
 
+namespace kernel::kinit {
+
+SECTION(".text.kinit")
+static void init_uname()
+{
+    kernel::sys_utsname = new new_utsname;
+    strcpy(kernel::sys_utsname->sysname, "Linux"); // linux compatible
+    strcpy(kernel::sys_utsname->nodename, "(none)");
+    strcpy(kernel::sys_utsname->release, "1.0.0");
+    strcpy(kernel::sys_utsname->version, "1.0.0");
+    strcpy(kernel::sys_utsname->machine, "x86");
+    strcpy(kernel::sys_utsname->domainname, "(none)");
+}
+
+} // namespace kernel::kinit
+
 extern "C" SECTION(".text.kinit") void NORETURN kernel_init(void)
 {
     asm_enable_sse();
@@ -107,6 +128,8 @@ extern "C" SECTION(".text.kinit") void NORETURN kernel_init(void)
     init_pic();
     init_pit();
 
+    kernel::kinit::init_uname();
+
     int ret = init_serial_port(PORT_SERIAL0);
     assert(ret == GB_OK);