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 <os/ArgumentParser.h>
|
||||
#include <os/File.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
Result<int> luna_main(int argc, char** argv)
|
||||
@ -26,6 +29,14 @@ Result<int> luna_main(int argc, char** argv)
|
||||
|
||||
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();
|
||||
|
||||
os::print("Username: ");
|
||||
|
48
apps/sh.cpp
48
apps/sh.cpp
@ -1,3 +1,4 @@
|
||||
#include <bits/termios.h>
|
||||
#include <errno.h>
|
||||
#include <luna/String.h>
|
||||
#include <luna/Vector.h>
|
||||
@ -11,6 +12,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -31,6 +33,11 @@ static Result<void> execute_command(StringView command)
|
||||
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;
|
||||
|
||||
const char* hostname = "";
|
||||
@ -41,7 +48,6 @@ Result<int> luna_main(int argc, char** argv)
|
||||
{
|
||||
StringView path;
|
||||
StringView command;
|
||||
bool interactive { false };
|
||||
|
||||
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 (path == "-")
|
||||
{
|
||||
input_file = File::standard_input();
|
||||
interactive = true;
|
||||
}
|
||||
if (path == "-") { input_file = File::standard_input(); }
|
||||
else
|
||||
{
|
||||
input_file = TRY(File::open(path, File::ReadOnly));
|
||||
input_file->set_close_on_exec();
|
||||
}
|
||||
|
||||
bool interactive = isatty(input_file->fd());
|
||||
|
||||
if (interactive)
|
||||
{
|
||||
// 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; }
|
||||
else { username = getenv("USER"); }
|
||||
endpwent();
|
||||
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
pid_t pgid = getpgid(0);
|
||||
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 (interactive) puts("exit");
|
||||
@ -116,11 +133,26 @@ Result<int> luna_main(int argc, char** argv)
|
||||
|
||||
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;
|
||||
TRY(os::Process::wait(child, &status));
|
||||
|
||||
if (interactive)
|
||||
{
|
||||
pid_t pgid = getpgid(0);
|
||||
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
|
||||
}
|
||||
|
||||
if (WIFSIGNALED(status))
|
||||
{
|
||||
int sig = WTERMSIG(status);
|
||||
|
26
apps/su.cpp
26
apps/su.cpp
@ -1,6 +1,7 @@
|
||||
#include <bits/termios.h>
|
||||
#include <os/ArgumentParser.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
@ -13,8 +14,24 @@ void restore_terminal()
|
||||
ioctl(fileno(stdin), TCSETS, &orig);
|
||||
}
|
||||
|
||||
void sigint_handler(int)
|
||||
{
|
||||
restore_terminal();
|
||||
raise(SIGINT);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (ioctl(fileno(stdin), TCGETS, &orig) < 0)
|
||||
@ -23,6 +40,12 @@ char* getpass()
|
||||
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);
|
||||
|
||||
struct termios tc = orig;
|
||||
@ -82,6 +105,8 @@ Result<int> luna_main(int argc, char** argv)
|
||||
|
||||
if ((prompt_password || getuid() != geteuid()) && *entry->pw_passwd)
|
||||
{
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
|
||||
char* pass = getpass();
|
||||
if (!pass) return 1;
|
||||
|
||||
@ -102,6 +127,7 @@ Result<int> luna_main(int argc, char** argv)
|
||||
chdir(entry->pw_dir);
|
||||
clearenv();
|
||||
setenv("PATH", "/bin:/sbin", 1);
|
||||
setpgid(0, 0);
|
||||
}
|
||||
|
||||
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 };
|
||||
regs->rax = (u64)invoke_syscall(regs, args, regs->rax);
|
||||
Scheduler::current()->process_pending_signals(regs);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -15,15 +15,42 @@
|
||||
static Buffer g_console_input;
|
||||
static bool g_eof { false };
|
||||
static bool g_echo { true };
|
||||
static bool g_stop_background_output { false };
|
||||
|
||||
static Option<pid_t> g_foreground_process_group;
|
||||
|
||||
Result<void> ConsoleDevice::create()
|
||||
{
|
||||
auto device = (SharedPtr<Device>)TRY(make_shared<ConsoleDevice>());
|
||||
g_foreground_process_group = {};
|
||||
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
|
||||
{
|
||||
TRY(handle_background_process_group(false, SIGTTIN));
|
||||
|
||||
if (length > g_console_input.size()) length = g_console_input.size();
|
||||
|
||||
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)
|
||||
{
|
||||
if (g_stop_background_output) TRY(handle_background_process_group(true, SIGTTOU));
|
||||
|
||||
TextConsole::write((const char*)buf, length);
|
||||
return length;
|
||||
}
|
||||
@ -63,19 +92,36 @@ void ConsoleDevice::did_press_key(char key)
|
||||
}
|
||||
|
||||
// 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;
|
||||
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();
|
||||
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("Free memory: %s", to_dynamic_unit(MemoryManager::free()).release_value().chars());
|
||||
@ -84,7 +130,7 @@ void ConsoleDevice::did_press_key(char key)
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == 'h' && (Keyboard::modifiers() & (Keyboard::LeftAlt | Keyboard::LeftControl)))
|
||||
if (key == 'h' && (Keyboard::modifiers() == (Keyboard::LeftAlt | Keyboard::LeftControl)))
|
||||
{
|
||||
dump_heap_usage();
|
||||
return;
|
||||
@ -113,15 +159,38 @@ Result<u64> ConsoleDevice::ioctl(int request, void* arg)
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
case TCSETS: {
|
||||
TRY(handle_background_process_group(true, SIGTTOU));
|
||||
|
||||
struct termios tc;
|
||||
if (!MemoryManager::copy_from_user_typed((const struct termios*)arg, &tc)) return err(EFAULT);
|
||||
if (tc.c_lflag & ECHO) g_echo = true;
|
||||
else
|
||||
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;
|
||||
}
|
||||
default: return err(EINVAL);
|
||||
|
@ -15,8 +15,6 @@ i64 invoke_syscall(Registers* regs, SyscallArgs args, u64 syscall)
|
||||
|
||||
auto rc = syscalls[syscall](regs, args);
|
||||
|
||||
Scheduler::current()->process_pending_signals(regs);
|
||||
|
||||
if (rc.has_error()) return -rc.error();
|
||||
return (i64)rc.value();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <luna/SafeArithmetic.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];
|
||||
u8* buf = (u8*)args[1];
|
||||
@ -31,6 +31,13 @@ Result<u64> sys_read(Registers*, SyscallArgs args)
|
||||
if (descriptor.should_block()) kernel_sleep(10);
|
||||
else
|
||||
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));
|
||||
|
@ -128,6 +128,20 @@ Result<u64> sys_setpgid(Registers*, SyscallArgs args)
|
||||
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)
|
||||
{
|
||||
int dirfd = (int)args[0];
|
||||
|
@ -11,5 +11,7 @@ Result<u64> sys_usleep(Registers*, SyscallArgs args)
|
||||
|
||||
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 "sys/Syscall.h"
|
||||
#include "thread/Scheduler.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];
|
||||
int* status_ptr = (int*)args[1];
|
||||
@ -21,7 +22,16 @@ Result<u64> sys_waitpid(Registers*, SyscallArgs args)
|
||||
|
||||
if (options & WNOHANG) return err(EAGAIN);
|
||||
|
||||
wait_for_child:
|
||||
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);
|
||||
}
|
||||
else if (pid == -1)
|
||||
@ -33,7 +43,16 @@ Result<u64> sys_waitpid(Registers*, SyscallArgs args)
|
||||
{
|
||||
if (options & WNOHANG) return err(EAGAIN);
|
||||
|
||||
wait_for_any_child:
|
||||
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);
|
||||
|
||||
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->is_kernel = false;
|
||||
thread->id = 1;
|
||||
thread->pgid = 1;
|
||||
thread->name = name;
|
||||
thread->auth = Credentials { .uid = 0, .euid = 0, .suid = 0, .gid = 0, .egid = 0, .sgid = 0 };
|
||||
|
||||
|
@ -110,6 +110,7 @@ enum class DefaultSignalAction
|
||||
Terminate,
|
||||
};
|
||||
|
||||
// FIXME: Implement coredumps for some signals.
|
||||
static constexpr DefaultSignalAction default_actions[] = {
|
||||
DefaultSignalAction::Terminate, // SIGHUP
|
||||
DefaultSignalAction::Terminate, // SIGINT
|
||||
@ -126,10 +127,13 @@ static constexpr DefaultSignalAction default_actions[] = {
|
||||
DefaultSignalAction::Terminate, // SIGPIPE
|
||||
DefaultSignalAction::Terminate, // SIGALRM
|
||||
DefaultSignalAction::Terminate, // SIGTERM
|
||||
DefaultSignalAction::Terminate, // SIGTTIN
|
||||
DefaultSignalAction::Terminate, // SIGTTOU
|
||||
};
|
||||
|
||||
void Thread::process_pending_signals(Registers* current_regs)
|
||||
{
|
||||
interrupted = false;
|
||||
for (int i = 0; i < NSIG; i++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
check(signo > 0 && signo <= NSIG);
|
||||
pending_signals |= 1 << (signo - 1);
|
||||
|
||||
if (state == ThreadState::Waiting || state == ThreadState::Sleeping)
|
||||
{
|
||||
interrupted = true;
|
||||
wake_up();
|
||||
}
|
||||
}
|
||||
|
||||
bool FileDescriptor::should_append()
|
||||
|
@ -84,6 +84,7 @@ struct Thread : public LinkedListNode<Thread>
|
||||
struct sigaction signal_handlers[NSIG];
|
||||
sigset_t signal_mask { 0 };
|
||||
sigset_t pending_signals { 0 };
|
||||
bool interrupted { false };
|
||||
|
||||
FPData fp_data;
|
||||
|
||||
@ -139,6 +140,8 @@ struct Thread : public LinkedListNode<Thread>
|
||||
|
||||
void process_pending_signals(Registers* current_regs);
|
||||
|
||||
bool will_invoke_signal_handler();
|
||||
|
||||
bool deliver_signal(int signo, Registers* current_regs);
|
||||
void sigreturn(Registers* current_regs);
|
||||
|
||||
|
@ -49,6 +49,8 @@ enum __signals
|
||||
SIGPIPE = 13,
|
||||
SIGALRM = 14,
|
||||
SIGTERM = 15,
|
||||
SIGTTIN = 16,
|
||||
SIGTTOU = 17,
|
||||
// FIXME: Add the remaining signals.
|
||||
__NSIG,
|
||||
};
|
||||
|
@ -13,9 +13,11 @@ struct termios
|
||||
|
||||
// Values for c_lflag.
|
||||
#define ECHO 1
|
||||
#define TOSTOP 2
|
||||
|
||||
// termios ioctl() requests.
|
||||
#define TCGETS 0
|
||||
#define TCSETS 1
|
||||
#define TIOCSPGRP 2
|
||||
|
||||
#endif
|
||||
|
@ -45,6 +45,9 @@ extern "C"
|
||||
/* Return the current process' effective group ID. */
|
||||
gid_t getegid(void);
|
||||
|
||||
/* Return a process' process group ID. */
|
||||
pid_t getpgid(pid_t pid);
|
||||
|
||||
/* Set the current process' user IDs. */
|
||||
int setuid(uid_t uid);
|
||||
|
||||
|
@ -33,6 +33,8 @@ extern "C"
|
||||
case SIGPIPE: return "Broken pipe";
|
||||
case SIGALRM: return "Alarm signal";
|
||||
case SIGTERM: return "Terminated";
|
||||
case SIGTTIN: return "Background process stopped (terminal input)";
|
||||
case SIGTTOU: return "Background process stopped (terminal output)";
|
||||
default: return "Unknown signal";
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +120,12 @@ extern "C"
|
||||
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)
|
||||
{
|
||||
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(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(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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user