diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index a8c3ae659e..a119dad55b 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2639,6 +2639,21 @@ int Process::sys$systrace(pid_t pid) return fd; } +int Process::sys$halt() +{ + if (!is_superuser()) + return -EPERM; + + dbgprintf("acquiring FS locks...\n"); + FS::lock_all(); + dbgprintf("syncing mounted filesystems...\n"); + FS::sync(); + dbgprintf("attempting system shutdown...\n"); + IO::out16(0x604, 0x2000); + + return ESUCCESS; +} + int Process::sys$reboot() { if (!is_superuser()) diff --git a/Kernel/Process.h b/Kernel/Process.h index 874ed84f9b..d027cfe3a4 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -203,6 +203,7 @@ public: int sys$release_shared_buffer(int shared_buffer_id); int sys$seal_shared_buffer(int shared_buffer_id); int sys$get_shared_buffer_size(int shared_buffer_id); + int sys$halt(); int sys$reboot(); static void initialize(); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 4f17862e41..6f1b25132f 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include #include #include @@ -285,12 +285,7 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3 case Syscall::SC_sched_getparam: return current->process().sys$sched_setparam((pid_t)arg1, (struct sched_param*)arg2); case Syscall::SC_halt: { - dbgprintf("<%u> halting! acquiring locks...\n"); - FS::lock_all(); - dbgprintf("<%u> halting! syncing...\n"); - FS::sync(); - dbgprintf("<%u> halting! bye, friends...\n"); - IO::out16(0x604, 0x2000); + return current->process().sys$halt(); break; } case Syscall::SC_reboot: { diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index a859bcd85b..4dd041224a 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -515,6 +515,12 @@ int fsync(int fd) return 0; } +int halt() +{ + int rc = syscall(SC_halt); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + int reboot() { int rc = syscall(SC_reboot); diff --git a/Libraries/LibC/unistd.h b/Libraries/LibC/unistd.h index a84353dc5a..cbf57265f3 100644 --- a/Libraries/LibC/unistd.h +++ b/Libraries/LibC/unistd.h @@ -93,6 +93,7 @@ char* getlogin(); int chown(const char* pathname, uid_t, gid_t); int fchown(int fd, uid_t, gid_t); int ftruncate(int fd, off_t length); +int halt(); int reboot(); enum { diff --git a/Userland/shutdown.cpp b/Userland/shutdown.cpp index cd2ffe67c1..0d1900fbf7 100644 --- a/Userland/shutdown.cpp +++ b/Userland/shutdown.cpp @@ -1,5 +1,6 @@ -#include #include +#include +#include int main(int argc, char** argv) { @@ -8,8 +9,10 @@ int main(int argc, char** argv) CArgsParserResult args = args_parser.parse(argc, argv); if (args.is_present("n")) { - syscall(SC_halt); - return 0; + if (halt() < 0) { + perror("shutdown"); + return 1; + } } else { args_parser.print_usage(); return 0;