Compare commits
5 Commits
1091798195
...
81e1fdf81e
Author | SHA1 | Date | |
---|---|---|---|
81e1fdf81e | |||
9f45026cc2 | |||
71ff763dd9 | |||
b64093dee5 | |||
d27ffce5db |
@ -1,7 +1,10 @@
|
|||||||
|
#include <bits/termios.h>
|
||||||
#include <luna/String.h>
|
#include <luna/String.h>
|
||||||
#include <os/ArgumentParser.h>
|
#include <os/ArgumentParser.h>
|
||||||
#include <os/File.h>
|
#include <os/File.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
Result<int> luna_main(int argc, char** argv)
|
Result<int> luna_main(int argc, char** argv)
|
||||||
@ -26,6 +29,14 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
|
|
||||||
if (username.is_empty())
|
if (username.is_empty())
|
||||||
{
|
{
|
||||||
|
signal(SIGTTOU, SIG_IGN);
|
||||||
|
|
||||||
|
if (isatty(STDIN_FILENO))
|
||||||
|
{
|
||||||
|
pid_t pgid = getpgid(0);
|
||||||
|
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
|
||||||
|
}
|
||||||
|
|
||||||
auto input = os::File::standard_input();
|
auto input = os::File::standard_input();
|
||||||
|
|
||||||
os::print("Username: ");
|
os::print("Username: ");
|
||||||
|
48
apps/sh.cpp
48
apps/sh.cpp
@ -1,3 +1,4 @@
|
|||||||
|
#include <bits/termios.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <luna/String.h>
|
#include <luna/String.h>
|
||||||
#include <luna/Vector.h>
|
#include <luna/Vector.h>
|
||||||
@ -11,6 +12,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -31,6 +33,11 @@ static Result<void> execute_command(StringView command)
|
|||||||
return os::Process::exec(args[0].view(), args.slice());
|
return os::Process::exec(args[0].view(), args.slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do nothing, but we need a handler so read() returns EINTR.
|
||||||
|
static void sigint_handler(int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
struct utsname g_sysinfo;
|
struct utsname g_sysinfo;
|
||||||
|
|
||||||
const char* hostname = "";
|
const char* hostname = "";
|
||||||
@ -41,7 +48,6 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
StringView path;
|
StringView path;
|
||||||
StringView command;
|
StringView command;
|
||||||
bool interactive { false };
|
|
||||||
|
|
||||||
SharedPtr<File> input_file;
|
SharedPtr<File> input_file;
|
||||||
|
|
||||||
@ -54,17 +60,15 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
|
|
||||||
if (!command.is_empty()) TRY(execute_command(command));
|
if (!command.is_empty()) TRY(execute_command(command));
|
||||||
|
|
||||||
if (path == "-")
|
if (path == "-") { input_file = File::standard_input(); }
|
||||||
{
|
|
||||||
input_file = File::standard_input();
|
|
||||||
interactive = true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
input_file = TRY(File::open(path, File::ReadOnly));
|
input_file = TRY(File::open(path, File::ReadOnly));
|
||||||
input_file->set_close_on_exec();
|
input_file->set_close_on_exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool interactive = isatty(input_file->fd());
|
||||||
|
|
||||||
if (interactive)
|
if (interactive)
|
||||||
{
|
{
|
||||||
// Set up everything to form a prompt.
|
// Set up everything to form a prompt.
|
||||||
@ -77,6 +81,12 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
if (pw) { username = pw->pw_name; }
|
if (pw) { username = pw->pw_name; }
|
||||||
else { username = getenv("USER"); }
|
else { username = getenv("USER"); }
|
||||||
endpwent();
|
endpwent();
|
||||||
|
|
||||||
|
signal(SIGTTOU, SIG_IGN);
|
||||||
|
signal(SIGINT, sigint_handler);
|
||||||
|
|
||||||
|
pid_t pgid = getpgid(0);
|
||||||
|
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@ -87,7 +97,14 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
os::print("%s@%s:%s%c ", username, hostname, cwd.chars(), prompt_end);
|
os::print("%s@%s:%s%c ", username, hostname, cwd.chars(), prompt_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cmd = TRY(input_file->read_line());
|
auto maybe_cmd = input_file->read_line();
|
||||||
|
if (maybe_cmd.has_error())
|
||||||
|
{
|
||||||
|
if (maybe_cmd.error() == EINTR) continue;
|
||||||
|
return maybe_cmd.release_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cmd = maybe_cmd.release_value();
|
||||||
if (cmd.is_empty())
|
if (cmd.is_empty())
|
||||||
{
|
{
|
||||||
if (interactive) puts("exit");
|
if (interactive) puts("exit");
|
||||||
@ -116,11 +133,26 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
|
|
||||||
pid_t child = TRY(os::Process::fork());
|
pid_t child = TRY(os::Process::fork());
|
||||||
|
|
||||||
if (child == 0) { TRY(execute_command(cmd.view())); }
|
if (child == 0)
|
||||||
|
{
|
||||||
|
if (interactive)
|
||||||
|
{
|
||||||
|
setpgid(0, 0);
|
||||||
|
pid_t pgid = getpgid(0);
|
||||||
|
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
|
||||||
|
}
|
||||||
|
TRY(execute_command(cmd.view()));
|
||||||
|
}
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
TRY(os::Process::wait(child, &status));
|
TRY(os::Process::wait(child, &status));
|
||||||
|
|
||||||
|
if (interactive)
|
||||||
|
{
|
||||||
|
pid_t pgid = getpgid(0);
|
||||||
|
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
|
||||||
|
}
|
||||||
|
|
||||||
if (WIFSIGNALED(status))
|
if (WIFSIGNALED(status))
|
||||||
{
|
{
|
||||||
int sig = WTERMSIG(status);
|
int sig = WTERMSIG(status);
|
||||||
|
26
apps/su.cpp
26
apps/su.cpp
@ -1,6 +1,7 @@
|
|||||||
#include <bits/termios.h>
|
#include <bits/termios.h>
|
||||||
#include <os/ArgumentParser.h>
|
#include <os/ArgumentParser.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
@ -13,8 +14,24 @@ void restore_terminal()
|
|||||||
ioctl(fileno(stdin), TCSETS, &orig);
|
ioctl(fileno(stdin), TCSETS, &orig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sigint_handler(int)
|
||||||
|
{
|
||||||
|
restore_terminal();
|
||||||
|
raise(SIGINT);
|
||||||
|
}
|
||||||
|
|
||||||
char* getpass()
|
char* getpass()
|
||||||
{
|
{
|
||||||
|
if (!isatty(STDIN_FILENO))
|
||||||
|
{
|
||||||
|
// FIXME: Just read from /dev/tty (the controlling terminal). Problem: that doesn't exist yet.
|
||||||
|
fprintf(stderr, "error: password must be read from a terminal!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pgid = getpgid(0);
|
||||||
|
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
|
||||||
|
|
||||||
fputs("Password: ", stdout);
|
fputs("Password: ", stdout);
|
||||||
|
|
||||||
if (ioctl(fileno(stdin), TCGETS, &orig) < 0)
|
if (ioctl(fileno(stdin), TCGETS, &orig) < 0)
|
||||||
@ -23,6 +40,12 @@ char* getpass()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_handler = sigint_handler;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
|
||||||
atexit(restore_terminal);
|
atexit(restore_terminal);
|
||||||
|
|
||||||
struct termios tc = orig;
|
struct termios tc = orig;
|
||||||
@ -82,6 +105,8 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
|
|
||||||
if ((prompt_password || getuid() != geteuid()) && *entry->pw_passwd)
|
if ((prompt_password || getuid() != geteuid()) && *entry->pw_passwd)
|
||||||
{
|
{
|
||||||
|
signal(SIGTTOU, SIG_IGN);
|
||||||
|
|
||||||
char* pass = getpass();
|
char* pass = getpass();
|
||||||
if (!pass) return 1;
|
if (!pass) return 1;
|
||||||
|
|
||||||
@ -102,6 +127,7 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
chdir(entry->pw_dir);
|
chdir(entry->pw_dir);
|
||||||
clearenv();
|
clearenv();
|
||||||
setenv("PATH", "/bin:/sbin", 1);
|
setenv("PATH", "/bin:/sbin", 1);
|
||||||
|
setpgid(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (login || entry->pw_uid != 0) setenv("USER", entry->pw_name, 1);
|
if (login || entry->pw_uid != 0) setenv("USER", entry->pw_name, 1);
|
||||||
|
@ -186,6 +186,7 @@ extern "C" void arch_interrupt_entry(Registers* regs)
|
|||||||
{
|
{
|
||||||
SyscallArgs args = { regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8, regs->r9 };
|
SyscallArgs args = { regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8, regs->r9 };
|
||||||
regs->rax = (u64)invoke_syscall(regs, args, regs->rax);
|
regs->rax = (u64)invoke_syscall(regs, args, regs->rax);
|
||||||
|
Scheduler::current()->process_pending_signals(regs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -15,15 +15,42 @@
|
|||||||
static Buffer g_console_input;
|
static Buffer g_console_input;
|
||||||
static bool g_eof { false };
|
static bool g_eof { false };
|
||||||
static bool g_echo { true };
|
static bool g_echo { true };
|
||||||
|
static bool g_stop_background_output { false };
|
||||||
|
|
||||||
|
static Option<pid_t> g_foreground_process_group;
|
||||||
|
|
||||||
Result<void> ConsoleDevice::create()
|
Result<void> ConsoleDevice::create()
|
||||||
{
|
{
|
||||||
auto device = (SharedPtr<Device>)TRY(make_shared<ConsoleDevice>());
|
auto device = (SharedPtr<Device>)TRY(make_shared<ConsoleDevice>());
|
||||||
|
g_foreground_process_group = {};
|
||||||
return DeviceRegistry::register_special_device(DeviceRegistry::Console, 0, device);
|
return DeviceRegistry::register_special_device(DeviceRegistry::Console, 0, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Result<void> handle_background_process_group(bool can_succeed, int signo)
|
||||||
|
{
|
||||||
|
if (!g_foreground_process_group.has_value()) return {};
|
||||||
|
|
||||||
|
auto foreground_pgrp = g_foreground_process_group.value();
|
||||||
|
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
if ((pid_t)current->pgid == foreground_pgrp) return {};
|
||||||
|
|
||||||
|
if ((current->signal_mask & (1 << (signo - 1))) || (current->signal_handlers[signo - 1].sa_handler == SIG_IGN))
|
||||||
|
{
|
||||||
|
if (can_succeed) return {};
|
||||||
|
return err(EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
current->send_signal(signo);
|
||||||
|
|
||||||
|
if (can_succeed) return err(EINTR);
|
||||||
|
return err(EIO);
|
||||||
|
}
|
||||||
|
|
||||||
Result<usize> ConsoleDevice::read(u8* buf, usize, usize length) const
|
Result<usize> ConsoleDevice::read(u8* buf, usize, usize length) const
|
||||||
{
|
{
|
||||||
|
TRY(handle_background_process_group(false, SIGTTIN));
|
||||||
|
|
||||||
if (length > g_console_input.size()) length = g_console_input.size();
|
if (length > g_console_input.size()) length = g_console_input.size();
|
||||||
|
|
||||||
memcpy(buf, g_console_input.data(), length);
|
memcpy(buf, g_console_input.data(), length);
|
||||||
@ -39,6 +66,8 @@ Result<usize> ConsoleDevice::read(u8* buf, usize, usize length) const
|
|||||||
|
|
||||||
Result<usize> ConsoleDevice::write(const u8* buf, usize, usize length)
|
Result<usize> ConsoleDevice::write(const u8* buf, usize, usize length)
|
||||||
{
|
{
|
||||||
|
if (g_stop_background_output) TRY(handle_background_process_group(true, SIGTTOU));
|
||||||
|
|
||||||
TextConsole::write((const char*)buf, length);
|
TextConsole::write((const char*)buf, length);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
@ -63,19 +92,36 @@ void ConsoleDevice::did_press_key(char key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ctrl+D
|
// Ctrl+D
|
||||||
if (key == 'd' && (Keyboard::modifiers() & Keyboard::LeftControl))
|
if (key == 'd' && (Keyboard::modifiers() == Keyboard::LeftControl))
|
||||||
{
|
{
|
||||||
if (g_temp_input.size() == 0) g_eof = true;
|
if (g_temp_input.size() == 0) g_eof = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == 'e' && (Keyboard::modifiers() & (Keyboard::LeftAlt | Keyboard::LeftControl)))
|
if (key == 'c' && (Keyboard::modifiers() == Keyboard::LeftControl))
|
||||||
|
{
|
||||||
|
g_temp_input.clear();
|
||||||
|
|
||||||
|
if (g_echo) TextConsole::wprintln(L"^C");
|
||||||
|
|
||||||
|
if (g_foreground_process_group.has_value())
|
||||||
|
{
|
||||||
|
Scheduler::for_each_in_process_group(g_foreground_process_group.value(), [](Thread* thread) {
|
||||||
|
thread->send_signal(SIGINT);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == 'e' && (Keyboard::modifiers() == (Keyboard::LeftAlt | Keyboard::LeftControl)))
|
||||||
{
|
{
|
||||||
Scheduler::dump_state();
|
Scheduler::dump_state();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == 'm' && (Keyboard::modifiers() & (Keyboard::LeftAlt | Keyboard::LeftControl)))
|
if (key == 'm' && (Keyboard::modifiers() == (Keyboard::LeftAlt | Keyboard::LeftControl)))
|
||||||
{
|
{
|
||||||
kinfoln("Total memory: %s", to_dynamic_unit(MemoryManager::total()).release_value().chars());
|
kinfoln("Total memory: %s", to_dynamic_unit(MemoryManager::total()).release_value().chars());
|
||||||
kinfoln("Free memory: %s", to_dynamic_unit(MemoryManager::free()).release_value().chars());
|
kinfoln("Free memory: %s", to_dynamic_unit(MemoryManager::free()).release_value().chars());
|
||||||
@ -84,7 +130,7 @@ void ConsoleDevice::did_press_key(char key)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == 'h' && (Keyboard::modifiers() & (Keyboard::LeftAlt | Keyboard::LeftControl)))
|
if (key == 'h' && (Keyboard::modifiers() == (Keyboard::LeftAlt | Keyboard::LeftControl)))
|
||||||
{
|
{
|
||||||
dump_heap_usage();
|
dump_heap_usage();
|
||||||
return;
|
return;
|
||||||
@ -113,15 +159,38 @@ Result<u64> ConsoleDevice::ioctl(int request, void* arg)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (g_echo) tc.c_lflag |= ECHO;
|
if (g_echo) tc.c_lflag |= ECHO;
|
||||||
|
if (g_stop_background_output) tc.c_lflag |= TOSTOP;
|
||||||
return MemoryManager::copy_to_user_typed((struct termios*)arg, &tc) ? 0 : err(EFAULT);
|
return MemoryManager::copy_to_user_typed((struct termios*)arg, &tc) ? 0 : err(EFAULT);
|
||||||
}
|
}
|
||||||
case TCSETS: {
|
case TCSETS: {
|
||||||
|
TRY(handle_background_process_group(true, SIGTTOU));
|
||||||
|
|
||||||
struct termios tc;
|
struct termios tc;
|
||||||
if (!MemoryManager::copy_from_user_typed((const struct termios*)arg, &tc)) return err(EFAULT);
|
if (!MemoryManager::copy_from_user_typed((const struct termios*)arg, &tc)) return err(EFAULT);
|
||||||
if (tc.c_lflag & ECHO) g_echo = true;
|
if (tc.c_lflag & ECHO) g_echo = true;
|
||||||
else
|
else
|
||||||
g_echo = false;
|
g_echo = false;
|
||||||
|
|
||||||
|
if (tc.c_lflag & TOSTOP) g_stop_background_output = true;
|
||||||
|
else
|
||||||
|
g_stop_background_output = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case TIOCSPGRP: {
|
||||||
|
TRY(handle_background_process_group(true, SIGTTOU));
|
||||||
|
|
||||||
|
pid_t pgid;
|
||||||
|
if (!MemoryManager::copy_from_user_typed((const pid_t*)arg, &pgid)) return err(EFAULT);
|
||||||
|
|
||||||
|
bool pgid_exists = false;
|
||||||
|
Scheduler::for_each_in_process_group(pgid, [&pgid_exists](Thread*) {
|
||||||
|
pgid_exists = true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if (!pgid_exists) return err(EPERM);
|
||||||
|
|
||||||
|
g_foreground_process_group = pgid;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
default: return err(EINVAL);
|
default: return err(EINVAL);
|
||||||
|
@ -15,8 +15,6 @@ i64 invoke_syscall(Registers* regs, SyscallArgs args, u64 syscall)
|
|||||||
|
|
||||||
auto rc = syscalls[syscall](regs, args);
|
auto rc = syscalls[syscall](regs, args);
|
||||||
|
|
||||||
Scheduler::current()->process_pending_signals(regs);
|
|
||||||
|
|
||||||
if (rc.has_error()) return -rc.error();
|
if (rc.has_error()) return -rc.error();
|
||||||
return (i64)rc.value();
|
return (i64)rc.value();
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <luna/SafeArithmetic.h>
|
#include <luna/SafeArithmetic.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
Result<u64> sys_read(Registers*, SyscallArgs args)
|
Result<u64> sys_read(Registers* regs, SyscallArgs args)
|
||||||
{
|
{
|
||||||
int fd = (int)args[0];
|
int fd = (int)args[0];
|
||||||
u8* buf = (u8*)args[1];
|
u8* buf = (u8*)args[1];
|
||||||
@ -31,6 +31,13 @@ Result<u64> sys_read(Registers*, SyscallArgs args)
|
|||||||
if (descriptor.should_block()) kernel_sleep(10);
|
if (descriptor.should_block()) kernel_sleep(10);
|
||||||
else
|
else
|
||||||
return err(EAGAIN);
|
return err(EAGAIN);
|
||||||
|
|
||||||
|
if (current->interrupted)
|
||||||
|
{
|
||||||
|
kdbgln("signal: read interrupted by signal");
|
||||||
|
if (current->will_invoke_signal_handler()) return err(EINTR);
|
||||||
|
current->process_pending_signals(regs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usize nread = TRY(descriptor.inode->read(buf, descriptor.offset, size));
|
usize nread = TRY(descriptor.inode->read(buf, descriptor.offset, size));
|
||||||
|
@ -128,6 +128,20 @@ Result<u64> sys_setpgid(Registers*, SyscallArgs args)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<u64> sys_getpgid(Registers*, SyscallArgs args)
|
||||||
|
{
|
||||||
|
pid_t pid = (pid_t)args[0];
|
||||||
|
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
if (pid == 0) pid = (pid_t)current->id;
|
||||||
|
|
||||||
|
if (pid < 0) return err(EINVAL);
|
||||||
|
|
||||||
|
auto* thread = TRY(Result<Thread*>::from_option(Scheduler::find_by_pid(pid), ESRCH));
|
||||||
|
|
||||||
|
return (u64)thread->pgid;
|
||||||
|
}
|
||||||
|
|
||||||
Result<u64> sys_fchmodat(Registers*, SyscallArgs args)
|
Result<u64> sys_fchmodat(Registers*, SyscallArgs args)
|
||||||
{
|
{
|
||||||
int dirfd = (int)args[0];
|
int dirfd = (int)args[0];
|
||||||
|
@ -11,5 +11,7 @@ Result<u64> sys_usleep(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
kernel_sleep(us / 1000);
|
kernel_sleep(us / 1000);
|
||||||
|
|
||||||
return 0;
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
|
return current->sleep_ticks_left;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
#include "Log.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include <bits/waitpid.h>
|
#include <bits/waitpid.h>
|
||||||
|
|
||||||
Result<u64> sys_waitpid(Registers*, SyscallArgs args)
|
Result<u64> sys_waitpid(Registers* regs, SyscallArgs args)
|
||||||
{
|
{
|
||||||
pid_t pid = (pid_t)args[0];
|
pid_t pid = (pid_t)args[0];
|
||||||
int* status_ptr = (int*)args[1];
|
int* status_ptr = (int*)args[1];
|
||||||
@ -21,7 +22,16 @@ Result<u64> sys_waitpid(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
if (options & WNOHANG) return err(EAGAIN);
|
if (options & WNOHANG) return err(EAGAIN);
|
||||||
|
|
||||||
|
wait_for_child:
|
||||||
if (thread->state != ThreadState::Exited) kernel_wait(pid);
|
if (thread->state != ThreadState::Exited) kernel_wait(pid);
|
||||||
|
if (current->interrupted)
|
||||||
|
{
|
||||||
|
kdbgln("signal: waitpid interrupted by signal");
|
||||||
|
if (current->will_invoke_signal_handler()) return err(EINTR);
|
||||||
|
current->process_pending_signals(regs);
|
||||||
|
goto wait_for_child;
|
||||||
|
}
|
||||||
|
|
||||||
check(thread->state == ThreadState::Exited);
|
check(thread->state == ThreadState::Exited);
|
||||||
}
|
}
|
||||||
else if (pid == -1)
|
else if (pid == -1)
|
||||||
@ -33,7 +43,16 @@ Result<u64> sys_waitpid(Registers*, SyscallArgs args)
|
|||||||
{
|
{
|
||||||
if (options & WNOHANG) return err(EAGAIN);
|
if (options & WNOHANG) return err(EAGAIN);
|
||||||
|
|
||||||
|
wait_for_any_child:
|
||||||
kernel_wait(pid);
|
kernel_wait(pid);
|
||||||
|
if (current->interrupted)
|
||||||
|
{
|
||||||
|
kdbgln("signal: waitpid interrupted by signal");
|
||||||
|
if (current->will_invoke_signal_handler()) return err(EINTR);
|
||||||
|
current->process_pending_signals(regs);
|
||||||
|
goto wait_for_any_child;
|
||||||
|
}
|
||||||
|
|
||||||
check(current->child_being_waited_for.value_or(-1) != -1);
|
check(current->child_being_waited_for.value_or(-1) != -1);
|
||||||
|
|
||||||
thread = TRY(Result<Thread*>::from_option(Scheduler::find_by_pid(*current->child_being_waited_for), ESRCH));
|
thread = TRY(Result<Thread*>::from_option(Scheduler::find_by_pid(*current->child_being_waited_for), ESRCH));
|
||||||
|
@ -135,6 +135,7 @@ namespace Scheduler
|
|||||||
thread->state = ThreadState::None;
|
thread->state = ThreadState::None;
|
||||||
thread->is_kernel = false;
|
thread->is_kernel = false;
|
||||||
thread->id = 1;
|
thread->id = 1;
|
||||||
|
thread->pgid = 1;
|
||||||
thread->name = name;
|
thread->name = name;
|
||||||
thread->auth = Credentials { .uid = 0, .euid = 0, .suid = 0, .gid = 0, .egid = 0, .sgid = 0 };
|
thread->auth = Credentials { .uid = 0, .euid = 0, .suid = 0, .gid = 0, .egid = 0, .sgid = 0 };
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ enum class DefaultSignalAction
|
|||||||
Terminate,
|
Terminate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME: Implement coredumps for some signals.
|
||||||
static constexpr DefaultSignalAction default_actions[] = {
|
static constexpr DefaultSignalAction default_actions[] = {
|
||||||
DefaultSignalAction::Terminate, // SIGHUP
|
DefaultSignalAction::Terminate, // SIGHUP
|
||||||
DefaultSignalAction::Terminate, // SIGINT
|
DefaultSignalAction::Terminate, // SIGINT
|
||||||
@ -126,10 +127,13 @@ static constexpr DefaultSignalAction default_actions[] = {
|
|||||||
DefaultSignalAction::Terminate, // SIGPIPE
|
DefaultSignalAction::Terminate, // SIGPIPE
|
||||||
DefaultSignalAction::Terminate, // SIGALRM
|
DefaultSignalAction::Terminate, // SIGALRM
|
||||||
DefaultSignalAction::Terminate, // SIGTERM
|
DefaultSignalAction::Terminate, // SIGTERM
|
||||||
|
DefaultSignalAction::Terminate, // SIGTTIN
|
||||||
|
DefaultSignalAction::Terminate, // SIGTTOU
|
||||||
};
|
};
|
||||||
|
|
||||||
void Thread::process_pending_signals(Registers* current_regs)
|
void Thread::process_pending_signals(Registers* current_regs)
|
||||||
{
|
{
|
||||||
|
interrupted = false;
|
||||||
for (int i = 0; i < NSIG; i++)
|
for (int i = 0; i < NSIG; i++)
|
||||||
{
|
{
|
||||||
int signo = i + 1;
|
int signo = i + 1;
|
||||||
@ -172,10 +176,33 @@ void Thread::process_pending_signals(Registers* current_regs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Thread::will_invoke_signal_handler()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NSIG; i++)
|
||||||
|
{
|
||||||
|
if (pending_signals & (1 << i))
|
||||||
|
{
|
||||||
|
int signo = i + 1;
|
||||||
|
if (signo != SIGKILL && signo != SIGSTOP && signal_mask & (1 << i)) continue;
|
||||||
|
auto handler = signal_handlers[i];
|
||||||
|
if (handler.sa_handler == SIG_IGN || handler.sa_handler == SIG_DFL) return false;
|
||||||
|
if (signo == SIGKILL || signo == SIGSTOP) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Thread::send_signal(int signo)
|
void Thread::send_signal(int signo)
|
||||||
{
|
{
|
||||||
check(signo > 0 && signo <= NSIG);
|
check(signo > 0 && signo <= NSIG);
|
||||||
pending_signals |= 1 << (signo - 1);
|
pending_signals |= 1 << (signo - 1);
|
||||||
|
|
||||||
|
if (state == ThreadState::Waiting || state == ThreadState::Sleeping)
|
||||||
|
{
|
||||||
|
interrupted = true;
|
||||||
|
wake_up();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileDescriptor::should_append()
|
bool FileDescriptor::should_append()
|
||||||
|
@ -84,6 +84,7 @@ struct Thread : public LinkedListNode<Thread>
|
|||||||
struct sigaction signal_handlers[NSIG];
|
struct sigaction signal_handlers[NSIG];
|
||||||
sigset_t signal_mask { 0 };
|
sigset_t signal_mask { 0 };
|
||||||
sigset_t pending_signals { 0 };
|
sigset_t pending_signals { 0 };
|
||||||
|
bool interrupted { false };
|
||||||
|
|
||||||
FPData fp_data;
|
FPData fp_data;
|
||||||
|
|
||||||
@ -139,6 +140,8 @@ struct Thread : public LinkedListNode<Thread>
|
|||||||
|
|
||||||
void process_pending_signals(Registers* current_regs);
|
void process_pending_signals(Registers* current_regs);
|
||||||
|
|
||||||
|
bool will_invoke_signal_handler();
|
||||||
|
|
||||||
bool deliver_signal(int signo, Registers* current_regs);
|
bool deliver_signal(int signo, Registers* current_regs);
|
||||||
void sigreturn(Registers* current_regs);
|
void sigreturn(Registers* current_regs);
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ enum __signals
|
|||||||
SIGPIPE = 13,
|
SIGPIPE = 13,
|
||||||
SIGALRM = 14,
|
SIGALRM = 14,
|
||||||
SIGTERM = 15,
|
SIGTERM = 15,
|
||||||
|
SIGTTIN = 16,
|
||||||
|
SIGTTOU = 17,
|
||||||
// FIXME: Add the remaining signals.
|
// FIXME: Add the remaining signals.
|
||||||
__NSIG,
|
__NSIG,
|
||||||
};
|
};
|
||||||
|
@ -13,9 +13,11 @@ struct termios
|
|||||||
|
|
||||||
// Values for c_lflag.
|
// Values for c_lflag.
|
||||||
#define ECHO 1
|
#define ECHO 1
|
||||||
|
#define TOSTOP 2
|
||||||
|
|
||||||
// termios ioctl() requests.
|
// termios ioctl() requests.
|
||||||
#define TCGETS 0
|
#define TCGETS 0
|
||||||
#define TCSETS 1
|
#define TCSETS 1
|
||||||
|
#define TIOCSPGRP 2
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,6 +45,9 @@ extern "C"
|
|||||||
/* Return the current process' effective group ID. */
|
/* Return the current process' effective group ID. */
|
||||||
gid_t getegid(void);
|
gid_t getegid(void);
|
||||||
|
|
||||||
|
/* Return a process' process group ID. */
|
||||||
|
pid_t getpgid(pid_t pid);
|
||||||
|
|
||||||
/* Set the current process' user IDs. */
|
/* Set the current process' user IDs. */
|
||||||
int setuid(uid_t uid);
|
int setuid(uid_t uid);
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ extern "C"
|
|||||||
case SIGPIPE: return "Broken pipe";
|
case SIGPIPE: return "Broken pipe";
|
||||||
case SIGALRM: return "Alarm signal";
|
case SIGALRM: return "Alarm signal";
|
||||||
case SIGTERM: return "Terminated";
|
case SIGTERM: return "Terminated";
|
||||||
|
case SIGTTIN: return "Background process stopped (terminal input)";
|
||||||
|
case SIGTTOU: return "Background process stopped (terminal output)";
|
||||||
default: return "Unknown signal";
|
default: return "Unknown signal";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,6 +120,12 @@ extern "C"
|
|||||||
return (gid_t)syscall(SYS_getegid);
|
return (gid_t)syscall(SYS_getegid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t getpgid(pid_t pid)
|
||||||
|
{
|
||||||
|
long rc = syscall(SYS_getpgid, pid);
|
||||||
|
__errno_return(rc, pid_t);
|
||||||
|
}
|
||||||
|
|
||||||
int setuid(uid_t uid)
|
int setuid(uid_t uid)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_setuid, uid);
|
long rc = syscall(SYS_setuid, uid);
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
|
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
|
||||||
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
|
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
|
||||||
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
|
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
|
||||||
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty)
|
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \
|
||||||
|
_e(getpgid)
|
||||||
|
|
||||||
enum Syscalls
|
enum Syscalls
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user