Compare commits

..

62 commits

Author SHA1 Message Date
Jonas 'Sortie' Termansen
cef7779f31 Handle SIGTERM in display(1).
Display a final frame with a message explaining what is happening that is
displayed while the system powers off, reboots, halts, when the user logs
out, or just exits the compositor.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
36a2d0ccc3 Sync login framebuffer code to libui. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
a180902247 Handle SIGTERM in login(8).
Display a final frame with a message explaining what is happening that is
displayed while the system powers off, reboots, or halts.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
5633699695 Modernize process and thread member variable names. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
e3af5ae322 Fix ppoll(2) EINTR handling. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
63a6509396 Add pstree(1) -is options. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
9d287d9433 Add chroot(8) -I option. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
7eb6a5f517 Modernize chroot(8). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
3cb2bf4590 Prevent init(8) from using the tty when a daemon uses it. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
e88c1ca56c Run daemons in their own session. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
035cd9b1a2 Add init groups.
Every process now has an init process like it has a session, and each
session belong to an init. Orphaned processes are reparented to its init
process. All descendent processes are SIGKILL'd when an init process exits
and creating additional processes/threads fails.

Add setinit(2) for becoming the init process for your child processes and
add getinit(2) for locating your init process.

Add TIOCSCTTY force flag that releases a terminal from its current session
and makes it the controlling terminal for the current session. This ioctl
is essential to transferring the controlling terminal to a nested init,
which has its own session.

Add TIOCUCTTY that releases the terminal as the controlling terminal for
its current session.

Remove INIT_PID as it is replaced by getinit(2).
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
189e79d62d Add service(8). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
08a834d932 Add checksum(1) --cache option. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
504415bc22 Add php port. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
7de016539a Revert "Update to perl-5.39.5."
This reverts commit 781ff8880f3e2d29e31460427bccf50cc1ec436e.

File/Spec was no longer being installed when --all-static, breaking
texinfo.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
bc2cf40dab Update to perl-5.39.5. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
e76b19fd2b Revert "Update to python-3.12.1."
This reverts commit 8ae8363167cc195f92803489e2f97391e2527c5f.

The libglib build broke due to no distutils module.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
5cec2e2f55 Update to python-3.12.1. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
4ba880938e Revert "Update to texinfo-7.1."
This reverts commit 9813bb1d13c625d48ecd950bfaafc274383ca049.

ffmpeg fails to build natively with the new makeinfo:

perl ./doc/texidep.pl . doc/ffmpeg-utils.texi doc/ffmpeg-utils.html >doc/ffmpeg-utils.html.d
makeinfo --html -I doc --no-split -D config-not-all --init-file=./doc/t2h.pm --output doc/ffmpeg-utils.html doc/ffmpeg-utils.texi
makeinfo: error parsing ./doc/t2h.pm: Undefined subroutine &Texinfo::Config::set_from_init_file called at ./doc/t2h.pm line 24.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
005eb40d27 Update to texinfo-7.1. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
adb08e530d Revert "Update to dash-0.5.12."
This reverts commit 16bedfc9630779c01ebae5513fd307e969c329de.

Something is wrong with the case pattern matching, maybe fnmatch?
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
544b52583e Update to dash-0.5.12. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
8f879f75a3 Revert "Update to freetype-2.13.2."
This reverts commit 5ad1e5f6054dd1e44ecb955b9326c1198ef17ff0.

configure runs make and crashes on a stack overflow in make.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
e5ae1e62e3 Update to freetype-2.13.2. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
6b158f7795 Revert "Update to bison-3.8.2."
This reverts commit b82fae810b42c5426d21c4dc153b32f086dd7fde.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
e74efce270 Update to bison-3.8.2. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
372370f37d Revert "Schedule interactive threads fairly under load."
This reverts commit 47731b91c37933943a73010c5a4494101cce52dc.

There is a rare freeze when the scheduler fails to run anything.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
8826615b48 Schedule interactive threads fairly under load.
Preempted threads are now removed from the runnable list until every
other thread has been preempted or the system goes idle. This ensures
threads that roundtrip to other threads get a full chance to perform
their work cooperatively without being starved by CPU intensive threads
whenever they yield.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
1e2a1f155a Kinda fix pager(1) man bullet points. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
257b3abe40 Fix ESP endian. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
4ea8396b5d Support booting with EFI. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
0871fa71c3 Add kernel(7) --firmware option. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
f9a346a6dc Add fatfs(8). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
ffafa81cd0 Add getty(8). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
0ab8901f8b Add terminal and interrupt support to com(4). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
8f4c3371f5 Add nyan(1). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
e9bfbc8d03 Work around pty deadlock. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
456e2ac596 Add cdrom mounting live environment. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
faff59cffc Revert "Parallelize driver initialization."
This reverts commit 0fef08bbc4.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
06fcbdb6ae Parallelize driver initialization. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
3fe2a32914 Speed up ata(4) 400 ns waits.
Waiting for any non-zero duration currently waits for at least one timer
cycle (10 ms), which is especially expensive during early boot.

The current workaround of simply reading the status 14 times seems really
suspicious although the osdev wiki documents it, but let's see how well it
works on real hardware, it's probably good enough.

Try to determine the initial selected drive to save one drive selection.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
a9b15bffe6 Decrease PS/2 timeouts. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
35e68109c9 Add uptime(1) -pr options. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
5248220e40 Add iso9660 filesystem implementation. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
35f4d2f000 Add kernel virtual address space usage debug information. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
9d317c462e Debug TCP socket state listing. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
250b95616b Add kernel heap allocation tracing debug facility. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
204576b7a8 Trianglix 4. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
8e3e058fd6 Add tix-check(8). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
bf2d489da1 Volatile release. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
d3d339b616 Add tix-upgrade(8). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
83ac75a083 Add tix-repository(8).
Support renaming, splitting, and deleting ports via RENAMES.

Unify on RUNTIME_DEPS for runtime dependencies.
2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
cc182e7912 Add signify port. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
d75c716891 Add pty(1). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
704ddbe061 Add getaddrinfo(1). 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
96d4615aee Enable stack smash protection by default. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
12a69346a0 Enable undefined behavior sanitization by default. 2024-06-22 17:26:05 +02:00
Jonas 'Sortie' Termansen
eede0df814 Handle SIGHUP in sh(1) and save shell history. 2024-06-22 17:26:04 +02:00
Jonas 'Sortie' Termansen
bab61702f3 Handle SIGWINCH in editor(1). 2024-06-22 17:23:51 +02:00
Jonas 'Sortie' Termansen
bf1d15957e Implement SIGWINCH. 2024-06-22 17:23:51 +02:00
Jonas 'Sortie' Termansen
ecd5217da8 Separate filesystem socket namespace inside chroots. 2024-06-22 17:23:51 +02:00
Jonas 'Sortie' Termansen
735dffd029 Fix sh(1) looping endlessly on input errors. 2024-06-22 17:23:51 +02:00
33 changed files with 791 additions and 355 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2023, 2024 Jonas 'Sortie' Termansen.
* Copyright (c) 2023 Juhani 'nortti' Krekelä.
*
* Permission to use, copy, modify, and distribute this software for any
@ -149,15 +149,15 @@ CONNECTION_MESSAGE_HANDLER_NO_AUX(shutdown)
{
(void) connection;
if ( msg->code == 0 )
exit(0);
display_exit(server->display, 0);
else if ( msg->code == 1 )
exit(1);
display_exit(server->display, 1);
else if ( msg->code == 2 )
exit(2);
display_exit(server->display, 2);
else if ( msg->code == 3 )
exit(3);
display_exit(server->display, 3);
else
exit(0);
display_exit(server->display, 0);
}
CONNECTION_MESSAGE_HANDLER_NO_AUX(create_window)

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -25,6 +25,7 @@
#include <display-protocol.h>
#include "display.h"
#include "server.h"
#include "window.h"

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2018, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014-2016, 2018, 2022-2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -23,6 +23,8 @@
#include <assert.h>
#include <err.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -47,6 +49,43 @@ void display_initialize(struct display* display)
{
memset(display, 0, sizeof(*display));
display->redraw = true;
display->running = true;
}
static int get_init_exit_plan(void)
{
FILE* fp = popen("/sbin/service default exit-code", "r");
if ( !fp )
return -1;
int result = -1;
char buffer[sizeof(int) * 3];
if ( fgets(buffer, sizeof(buffer), fp) && buffer[0] )
result = atoi(buffer);
pclose(fp);
return result;
}
void display_exit(struct display* display, int exit_code)
{
display->running = false;
display->exit_code = exit_code;
int plan = exit_code == -1 ? get_init_exit_plan() : exit_code;
display->announcement = "Exiting...";
if ( plan == 0 )
display->announcement = "Powering off...";
else if ( plan == 1 )
display->announcement = "Rebooting...";
else if ( plan == 2 )
display->announcement = "Halting...";
else if ( plan == 3 )
display->announcement = "Reinitializing operating system...";
else if ( getenv("LOGIN_PID") ) // TODO: display -l?
{
intmax_t login_pid = strtoimax(getenv("LOGIN_PID"), NULL, 10);
if ( login_pid == getppid() )
display->announcement = "Logging out...";
}
display->redraw = true;
}
void assert_is_well_formed_display_list(struct display* display)
@ -281,6 +320,31 @@ static void wallpaper(struct framebuffer fb)
}
}
static void display_render_exit(struct display* display, struct framebuffer fb)
{
for ( int yoff = -1; yoff <= 1; yoff++ )
{
for ( int xoff = -1; xoff <= 1; xoff++ )
{
struct framebuffer msgfb = fb;
int y = (fb.yres - FONT_HEIGHT) / 2 + yoff;
msgfb = framebuffer_cut_top_y(msgfb, y);
int w = strlen(display->announcement) * (FONT_WIDTH+1);
int x = (fb.xres - w) / 2 + xoff;
msgfb = framebuffer_cut_left_x(msgfb, x);
render_text(msgfb, display->announcement, make_color_a(0, 0, 0, 64));
}
}
struct framebuffer msgfb = fb;
int y = (fb.yres - FONT_HEIGHT) / 2;
msgfb = framebuffer_cut_top_y(msgfb, y);
int w = strlen(display->announcement) * (FONT_WIDTH+1);
int x = (fb.xres - w) / 2;
msgfb = framebuffer_cut_left_x(msgfb, x);
render_text(msgfb, display->announcement, make_color(255, 255, 255));
}
void display_composit(struct display* display, struct framebuffer fb)
{
struct damage_rect damage_rect = display->damage_rect;
@ -301,6 +365,12 @@ void display_composit(struct display* display, struct framebuffer fb)
framebuffer_copy_to_framebuffer(fb, display->wallpaper);
if ( display->announcement )
{
display_render_exit(display, fb);
return;
}
for ( struct window* window = display->bottom_window;
window;
window = window->above_window )
@ -482,11 +552,15 @@ void display_keyboard_event(struct display* display, uint32_t codepoint)
case KBKEY_RSUPER: display->key_rsuper = kbkey > 0; break;
}
if ( display->key_lctrl && display->key_lalt && kbkey == KBKEY_DELETE )
exit(0);
display_exit(display, -1);
if ( display->key_lctrl && display->key_lalt && kbkey == KBKEY_T )
{
if ( !fork() )
{
sigset_t sigterm;
sigemptyset(&sigterm);
sigaddset(&sigterm, SIGTERM);
sigprocmask(SIG_UNBLOCK, &sigterm, NULL);
execlp("terminal", "terminal", (char*) NULL);
_exit(127);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2017, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014-2017, 2022-2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -119,5 +119,5 @@ int main(int argc, char* argv[])
server_mainloop(&server);
return 0;
return display.exit_code;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2022, 2023, 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -68,14 +68,19 @@ struct display
bool key_rsuper;
bool codepoint_discard;
bool redraw;
bool running;
int pointer_x;
int pointer_y;
enum mouse_state mouse_state;
size_t mouse_byte_count;
uint8_t mouse_bytes[MOUSE_PACKET_SIZE];
const char* announcement;
int exit_code;
};
void display_initialize(struct display* display);
void display_exit(struct display* display, int exit_code);
void assert_is_well_formed_display_list(struct display* display);
void assert_is_well_formed_display(struct display* display);
void display_link_window_at_top(struct display* display, struct window* window);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2016, 2023, 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -28,6 +28,7 @@
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@ -40,6 +41,14 @@
#include "server.h"
#include "vgafont.h"
static volatile sig_atomic_t got_sigterm;
static void on_sigterm(int signum)
{
(void) signum;
got_sigterm = 1;
}
static int open_local_server_socket(const char* path, int flags)
{
size_t path_length = strlen(path);
@ -196,9 +205,24 @@ void server_poll(struct server* server)
}
size_t pfds_used = cpfd_off + connections_polled;
int num_events = ppoll(pfds, pfds_used, NULL, NULL);
sigset_t mask;
sigprocmask(SIG_SETMASK, NULL, &mask);
sigdelset(&mask, SIGTERM);
int num_events = ppoll(pfds, pfds_used, NULL, &mask);
if ( got_sigterm )
{
display_exit(server->display, -1);
got_sigterm = 0;
}
if ( num_events < 0 )
{
if ( errno == EINTR )
return;
err(1, "poll");
}
if ( pfds[0].revents )
{
@ -273,9 +297,20 @@ void server_poll(struct server* server)
void server_mainloop(struct server* server)
{
while ( true )
sigset_t sigterm, oldset;
sigemptyset(&sigterm);
sigaddset(&sigterm, SIGTERM);
sigprocmask(SIG_BLOCK, &sigterm, &oldset);
struct sigaction sa = { .sa_handler = on_sigterm }, old_sa;
sigaction(SIGTERM, &sa, &old_sa);
while ( server->display->running )
{
display_render(server->display);
server_poll(server);
}
display_render(server->display);
sigaction(SIGTERM, &old_sa, NULL);
sigprocmask(SIG_SETMASK, &oldset, NULL);
}

View file

@ -3256,6 +3256,9 @@ static void init(void)
DAEMON_STATE_FINISHING);
default_daemon_exit_code =
WCONSTRUCT(WNATURE_EXITED, caught_exit_signal, 0);
default_daemon->exit_code = default_daemon_exit_code;
default_daemon->exit_code_meaning =
EXIT_CODE_MEANING_POWEROFF_REBOOT;
}
caught_exit_signal = -1;

View file

@ -23,6 +23,8 @@
|
.Sy enable
|
.Sy exit-code
|
.Sy kill
|
.Sy pid
@ -177,6 +179,10 @@ command.
The daemon only starts if the
.Ar source-daemon
is running.
.It Sy exit-code
Write the exit code of the
.Ar daemon ,
or the empty string if it has not exited.
.It Sy kill
Kill the
.Ar daemon

View file

@ -521,6 +521,8 @@ int main(int argc, char* argv[])
fprintf(fp, "status %s\n", daemon);
else if ( !strcmp(command, "pid") )
fprintf(fp, "status %s\n", daemon);
else if ( !strcmp(command, "exit-code") )
fprintf(fp, "status %s\n", daemon);
else if ( !strcmp(command, "requirements") ||
!strcmp(command, "dependents") ||
!strcmp(command, "edges") )
@ -562,6 +564,19 @@ int main(int argc, char* argv[])
}
}
}
else if ( !strcmp(command, "exit-code") )
{
for ( size_t i = 1; i < tokens_count; i++ )
{
if ( !strncmp(tokens[i], "exit=", strlen("exit=")) )
{
const char* arg = tokens[i] + strlen("exit=");
if ( strcmp(arg, "n/a") )
puts(arg);
break;
}
}
}
else if ( !strcmp(command, "requirements") ||
!strcmp(command, "dependents") ||
!strcmp(command, "edges") )

View file

@ -250,6 +250,7 @@ int DevCOMPort::ioctl(ioctx_t* ctx, int cmd, uintptr_t arg)
const struct winsize* user_ws = (const struct winsize*) arg;
if ( !ctx->copy_from_src(&ws, user_ws, sizeof(ws)) )
return -1;
winch();
return 0;
}
lock.Reset();

View file

@ -679,9 +679,9 @@ Ref<Descriptor> Descriptor::open(ioctx_t* ctx, const char* filename, int flags,
mode_t mode)
{
Process* process = CurrentProcess();
kthread_mutex_lock(&process->idlock);
kthread_mutex_lock(&process->id_lock);
mode &= ~process->umask;
kthread_mutex_unlock(&process->idlock);
kthread_mutex_unlock(&process->id_lock);
if ( !filename[0] )
return errno = ENOENT, Ref<Descriptor>();
@ -840,9 +840,9 @@ Ref<Descriptor> Descriptor::open_elem(ioctx_t* ctx, const char* filename,
int Descriptor::mkdir(ioctx_t* ctx, const char* filename, mode_t mode)
{
Process* process = CurrentProcess();
kthread_mutex_lock(&process->idlock);
kthread_mutex_lock(&process->id_lock);
mode &= ~process->umask;
kthread_mutex_unlock(&process->idlock);
kthread_mutex_unlock(&process->id_lock);
char* final;
Ref<Descriptor> dir = OpenDirContainingPath(ctx, Ref<Descriptor>(this),

View file

@ -29,14 +29,14 @@ namespace Sortix {
uid_t sys_getuid()
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
return process->uid;
}
int sys_setuid(uid_t uid)
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
// TODO: Implement security checks in many place across the operating system
// and until then allow anyone to do this to not pretend to be secure.
process->uid = uid;
@ -47,14 +47,14 @@ int sys_setuid(uid_t uid)
gid_t sys_getgid()
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
return process->gid;
}
int sys_setgid(gid_t gid)
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
// TODO: Implement security checks in many place across the operating system
// and until then allow anyone to do this to not pretend to be secure.
process->gid = gid;
@ -65,14 +65,14 @@ int sys_setgid(gid_t gid)
uid_t sys_geteuid()
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
return process->euid;
}
int sys_seteuid(uid_t euid)
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
// TODO: Implement security checks in many place across the operating system
// and until then allow anyone to do this to not pretend to be secure.
process->euid = euid;
@ -82,14 +82,14 @@ int sys_seteuid(uid_t euid)
gid_t sys_getegid()
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
return process->egid;
}
int sys_setegid(gid_t egid)
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
// TODO: Implement security checks in many place across the operating system
// and until then allow anyone to do this to not pretend to be secure.
process->egid = egid;

View file

@ -66,17 +66,17 @@ public:
pid_t pid;
public:
kthread_mutex_t nicelock;
kthread_mutex_t nice_lock;
int nice;
public:
kthread_mutex_t idlock;
kthread_mutex_t id_lock;
uid_t uid, euid;
gid_t gid, egid;
mode_t umask;
private:
kthread_mutex_t ptrlock;
kthread_mutex_t ptr_lock;
Ref<Descriptor> tty;
Ref<Descriptor> root;
Ref<Descriptor> cwd;
@ -112,34 +112,34 @@ public:
public:
Process* parent;
Process* prevsibling;
Process* nextsibling;
Process* firstchild;
Process* zombiechild;
Process* prev_sibling;
Process* next_sibling;
Process* first_child;
Process* zombie_child;
Process* group;
Process* groupprev;
Process* groupnext;
Process* groupfirst;
Process* group_prev;
Process* group_next;
Process* group_first;
Process* session;
Process* sessionprev;
Process* sessionnext;
Process* sessionfirst;
Process* session_prev;
Process* session_next;
Process* session_first;
Process* init;
Process* initprev;
Process* initnext;
Process* initfirst;
kthread_mutex_t childlock;
kthread_mutex_t parentlock;
kthread_cond_t zombiecond;
bool iszombie;
bool nozombify;
Process* init_prev;
Process* init_next;
Process* init_first;
kthread_mutex_t child_lock;
kthread_mutex_t parent_lock;
kthread_cond_t zombie_cond;
bool is_zombie;
bool no_zombify;
bool limbo;
bool is_init_exiting;
int exit_code;
public:
Thread* firstthread;
kthread_mutex_t threadlock;
Thread* first_thread;
kthread_mutex_t thread_lock;
size_t threads_not_exiting_count;
bool threads_exiting;

View file

@ -79,8 +79,8 @@ public:
struct thread_registers registers;
size_t id;
Process* process;
Thread* prevsibling;
Thread* nextsibling;
Thread* prev_sibling;
Thread* next_sibling;
Thread* scheduler_list_prev;
Thread* scheduler_list_next;
volatile ThreadState state;
@ -88,12 +88,12 @@ public:
sigset_t signal_mask;
sigset_t saved_signal_mask;
stack_t signal_stack;
addr_t kernelstackpos;
size_t kernelstacksize;
addr_t kernel_stack_pos;
size_t kernel_stack_size;
size_t signal_count;
uintptr_t signal_single_frame;
uintptr_t signal_canary;
bool kernelstackmalloced;
bool kernel_stack_malloced;
bool pledged_destruction;
bool force_no_signals;
bool signal_single;

View file

@ -27,7 +27,7 @@ namespace Sortix {
void SetupUserIOCtx(ioctx_t* ctx)
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
ctx->uid = ctx->auth_uid = process->uid;
ctx->gid = ctx->auth_gid = process->gid;
ctx->copy_to_dest = CopyToUser;
@ -39,7 +39,7 @@ void SetupUserIOCtx(ioctx_t* ctx)
void SetupKernelIOCtx(ioctx_t* ctx)
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
ctx->uid = ctx->auth_uid = process->uid;
ctx->gid = ctx->auth_gid = process->gid;
ctx->copy_to_dest = CopyToKernel;

View file

@ -374,17 +374,17 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
ptable.Reset();
system->addrspace = Memory::GetAddressSpace();
system->group = system;
system->groupprev = NULL;
system->groupnext = NULL;
system->groupfirst = system;
system->group_prev = NULL;
system->group_next = NULL;
system->group_first = system;
system->session = system;
system->sessionprev = NULL;
system->sessionnext = NULL;
system->sessionfirst = system;
system->session_prev = NULL;
system->session_next = NULL;
system->session_first = system;
system->init = NULL;
system->initprev = NULL;
system->initnext = NULL;
system->initfirst = NULL;
system->init_prev = NULL;
system->init_next = NULL;
system->init_first = NULL;
if ( !(system->program_image_path = String::Clone("<kernel process>")) )
Panic("Unable to clone string for system process name");
@ -396,10 +396,10 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
Thread* idlethread = new Thread();
idlethread->name = "idle";
idlethread->process = system;
idlethread->kernelstackpos = (addr_t) stack;
idlethread->kernelstacksize = STACK_SIZE;
idlethread->kernelstackmalloced = false;
system->firstthread = idlethread;
idlethread->kernel_stack_pos = (addr_t) stack;
idlethread->kernel_stack_size = STACK_SIZE;
idlethread->kernel_stack_malloced = false;
system->first_thread = idlethread;
system->threads_not_exiting_count = 1;
Scheduler::SetIdleThread(idlethread);
@ -667,23 +667,23 @@ static void BootThread(void* /*user*/)
kthread_mutex_lock(&process_family_lock);
Process* kernel_process = CurrentProcess();
init->parent = kernel_process;
init->nextsibling = kernel_process->firstchild;
init->prevsibling = NULL;
if ( kernel_process->firstchild )
kernel_process->firstchild->prevsibling = init;
kernel_process->firstchild = init;
init->next_sibling = kernel_process->first_child;
init->prev_sibling = NULL;
if ( kernel_process->first_child )
kernel_process->first_child->prev_sibling = init;
kernel_process->first_child = init;
init->group = init;
init->groupprev = NULL;
init->groupnext = NULL;
init->groupfirst = init;
init->group_prev = NULL;
init->group_next = NULL;
init->group_first = init;
init->session = init;
init->sessionprev = NULL;
init->sessionnext = NULL;
init->sessionfirst = init;
init->session_prev = NULL;
init->session_next = NULL;
init->session_first = init;
init->init = init;
init->initprev = NULL;
init->initnext = NULL;
init->initfirst = init;
init->init_prev = NULL;
init->init_next = NULL;
init->init_first = init;
kthread_mutex_unlock(&process_family_lock);
// TODO: Why don't we fork from pid=0 and this is done for us?

View file

@ -258,9 +258,9 @@ void kthread_exit()
// only threads in this process, except the initial thread. Otherwise more
// threads may appear, and we can't conclude whether this is the last thread
// in the process to exit.
kthread_mutex_lock(&process->threadlock);
kthread_mutex_lock(&process->thread_lock);
bool is_last_to_exit = --process->threads_not_exiting_count == 0;
kthread_mutex_unlock(&process->threadlock);
kthread_mutex_unlock(&process->thread_lock);
// All other threads in the process have committed to exiting, though they
// might not have exited yet. However, we know they are only running the
// below code that schedules thread termination. It's therefore safe to run

View file

@ -202,10 +202,10 @@ PingSocket::PingSocket(int af)
dev = (dev_t) this;
ino = (ino_t) this;
type = S_IFSOCK;
kthread_mutex_lock(&process->idlock);
kthread_mutex_lock(&process->id_lock);
stat_uid = process->uid;
stat_gid = process->gid;
kthread_mutex_unlock(&process->idlock);
kthread_mutex_unlock(&process->id_lock);
stat_mode = 0600 | this->type;
supports_iovec = true;
socket_lock = KTHREAD_MUTEX_INITIALIZER;

View file

@ -2417,10 +2417,10 @@ TCPSocketNode::TCPSocketNode(TCPSocket* socket)
dev = (dev_t) this;
ino = (ino_t) this;
type = S_IFSOCK;
kthread_mutex_lock(&process->idlock);
kthread_mutex_lock(&process->id_lock);
stat_uid = process->uid;
stat_gid = process->gid;
kthread_mutex_unlock(&process->idlock);
kthread_mutex_unlock(&process->id_lock);
stat_mode = 0600 | this->type;
}

View file

@ -175,10 +175,10 @@ UDPSocket::UDPSocket(int af)
dev = (dev_t) this;
ino = (ino_t) this;
type = S_IFSOCK;
kthread_mutex_lock(&process->idlock);
kthread_mutex_lock(&process->id_lock);
stat_uid = process->uid;
stat_gid = process->gid;
kthread_mutex_unlock(&process->idlock);
kthread_mutex_unlock(&process->id_lock);
stat_mode = 0600 | this->type;
supports_iovec = true;
socket_lock = KTHREAD_MUTEX_INITIALIZER;

View file

@ -79,15 +79,15 @@ Process::Process()
addrspace = 0;
pid = 0;
nicelock = KTHREAD_MUTEX_INITIALIZER;
nice_lock = KTHREAD_MUTEX_INITIALIZER;
nice = 0;
idlock = KTHREAD_MUTEX_INITIALIZER;
id_lock = KTHREAD_MUTEX_INITIALIZER;
uid = euid = 0;
gid = egid = 0;
umask = 0022;
ptrlock = KTHREAD_MUTEX_INITIALIZER;
ptr_lock = KTHREAD_MUTEX_INITIALIZER;
// tty set to null reference in the member constructor.
// root set to null reference in the member constructor.
// cwd set to null reference in the member constructor.
@ -116,31 +116,31 @@ Process::Process()
sigreturn = NULL;
parent = NULL;
prevsibling = NULL;
nextsibling = NULL;
firstchild = NULL;
zombiechild = NULL;
prev_sibling = NULL;
next_sibling = NULL;
first_child = NULL;
zombie_child = NULL;
group = NULL;
groupprev = NULL;
groupnext = NULL;
groupfirst = NULL;
group_prev = NULL;
group_next = NULL;
group_first = NULL;
session = NULL;
sessionprev = NULL;
sessionnext = NULL;
sessionfirst = NULL;
session_prev = NULL;
session_next = NULL;
session_first = NULL;
init = NULL;
initprev = NULL;
initnext = NULL;
initfirst = NULL;
zombiecond = KTHREAD_COND_INITIALIZER;
iszombie = false;
nozombify = false;
init_prev = NULL;
init_next = NULL;
init_first = NULL;
zombie_cond = KTHREAD_COND_INITIALIZER;
is_zombie = false;
no_zombify = false;
limbo = false;
is_init_exiting = false;
exit_code = -1;
firstthread = NULL;
threadlock = KTHREAD_MUTEX_INITIALIZER;
first_thread = NULL;
thread_lock = KTHREAD_MUTEX_INITIALIZER;
threads_not_exiting_count = 0;
threads_exiting = false;
@ -170,15 +170,15 @@ Process::~Process() // process_family_lock taken
if ( alarm_timer.IsAttached() )
alarm_timer.Detach();
delete[] program_image_path;
assert(!zombiechild);
assert(!zombie_child);
assert(!init);
assert(!session);
assert(!group);
assert(!parent);
assert(!initfirst);
assert(!sessionfirst);
assert(!groupfirst);
assert(!firstchild);
assert(!init_first);
assert(!session_first);
assert(!group_first);
assert(!first_child);
assert(!addrspace);
assert(!segments);
assert(!dtable);
@ -195,7 +195,7 @@ Process::~Process() // process_family_lock taken
void Process::BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtable)
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(!this->dtable);
assert(!this->mtable);
this->dtable = dtable;
@ -204,7 +204,7 @@ void Process::BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtabl
void Process::BootstrapDirectories(Ref<Descriptor> root)
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(!this->root);
assert(!this->cwd);
this->root = root;
@ -223,43 +223,43 @@ void Process::OnLastThreadExit()
// Forbid any more processes and threads from being created, so this
// loop will always terminate.
is_init_exiting = true;
Process* process = firstchild;
Process* process = first_child;
while ( process )
{
if ( process->pid != 0 )
process->DeliverSignal(SIGKILL);
if ( process->init == process )
process->is_init_exiting = true;
if ( process->firstchild )
process = process->firstchild;
while ( process && process != this && !process->nextsibling )
if ( process->first_child )
process = process->first_child;
while ( process && process != this && !process->next_sibling )
process = process->parent;
if ( process == this )
break;
process = process->nextsibling;
process = process->next_sibling;
}
// NotifyChildExit always signals zombiecond for init when
// NotifyChildExit always signals zombie_cond for init when
// is_init_exiting is true.
while ( firstchild )
kthread_cond_wait(&zombiecond, &process_family_lock);
while ( first_child )
kthread_cond_wait(&zombie_cond, &process_family_lock);
}
}
void Process::OnThreadDestruction(Thread* thread)
{
assert(thread->process == this);
kthread_mutex_lock(&threadlock);
if ( thread->prevsibling )
thread->prevsibling->nextsibling = thread->nextsibling;
if ( thread->nextsibling )
thread->nextsibling->prevsibling = thread->prevsibling;
if ( thread == firstthread )
firstthread = thread->nextsibling;
if ( firstthread )
firstthread->prevsibling = NULL;
thread->prevsibling = thread->nextsibling = NULL;
bool threadsleft = firstthread;
kthread_mutex_unlock(&threadlock);
kthread_mutex_lock(&thread_lock);
if ( thread->prev_sibling )
thread->prev_sibling->next_sibling = thread->next_sibling;
if ( thread->next_sibling )
thread->next_sibling->prev_sibling = thread->prev_sibling;
if ( thread == first_thread )
first_thread = thread->next_sibling;
if ( first_thread )
first_thread->prev_sibling = NULL;
thread->prev_sibling = thread->next_sibling = NULL;
bool threadsleft = first_thread;
kthread_mutex_unlock(&thread_lock);
// We are called from the threads destructor, let it finish before we
// we handle the situation by killing ourselves.
@ -275,7 +275,7 @@ void Process__AfterLastThreadExit(void* user)
void Process::ScheduleDeath()
{
// All our threads must have exited at this point.
assert(!firstthread);
assert(!first_thread);
Worker::Schedule(Process__AfterLastThreadExit, this);
}
@ -284,7 +284,7 @@ void Process::ScheduleDeath()
// process after this call as another thread may garbage collect it.
void Process::AbortConstruction()
{
nozombify = true;
no_zombify = true;
ScheduleDeath();
}
@ -311,7 +311,7 @@ void Process::LastPrayer()
{
assert(this);
// This must never be called twice.
assert(!iszombie);
assert(!is_zombie);
// This must be called from a thread using another address space as the
// address space of this process is about to be destroyed.
@ -319,7 +319,7 @@ void Process::LastPrayer()
assert(curthread->process != this);
// This can't be called if the process is still alive.
assert(!firstthread);
assert(!first_thread);
// Disarm and detach all the timers in the process.
DeleteTimers();
@ -348,7 +348,7 @@ void Process::LastPrayer()
ScopedLock family_lock(&process_family_lock);
iszombie = true;
is_zombie = true;
// Init is nice and will gladly raise our orphaned children and zombies.
// Child processes can't be reparented away if we're init. OnLastThreadExit
@ -358,33 +358,33 @@ void Process::LastPrayer()
if ( init == this )
{
assert(is_init_exiting);
assert(!firstchild);
assert(!first_child);
}
while ( firstchild )
while ( first_child )
{
Process* process = firstchild;
firstchild = process->nextsibling;
Process* process = first_child;
first_child = process->next_sibling;
process->parent = init;
process->prevsibling = NULL;
process->nextsibling = init->firstchild;
if ( init->firstchild )
init->firstchild->prevsibling = process;
init->firstchild = process;
process->nozombify = true;
process->prev_sibling = NULL;
process->next_sibling = init->first_child;
if ( init->first_child )
init->first_child->prev_sibling = process;
init->first_child = process;
process->no_zombify = true;
}
// Since we have no more children (they are with init now), we don't
// have to worry about new zombie processes showing up, so just collect
// those that are left. Then we satisfiy the invariant !zombiechild that
// those that are left. Then we satisfiy the invariant !zombie_child that
// applies on process termination.
while ( zombiechild )
while ( zombie_child )
{
Process* zombie = zombiechild;
zombiechild = zombie->nextsibling;
zombie->nextsibling = NULL;
if ( zombiechild )
zombiechild->prevsibling = NULL;
zombie->nozombify = true;
Process* zombie = zombie_child;
zombie_child = zombie->next_sibling;
zombie->next_sibling = NULL;
if ( zombie_child )
zombie_child->prev_sibling = NULL;
zombie->no_zombify = true;
zombie->WaitedFor();
}
// Remove ourself from our process group.
@ -397,7 +397,7 @@ void Process::LastPrayer()
if ( init )
init->InitRemoveMember(this);
bool zombify = !nozombify;
bool zombify = !no_zombify;
// This class instance will be destroyed by our parent process when it
// has received and acknowledged our death.
@ -413,7 +413,7 @@ void Process::WaitedFor() // process_family_lock taken
{
parent = NULL;
limbo = false;
if ( groupfirst || sessionfirst || initfirst )
if ( group_first || session_first || init_first )
limbo = true;
if ( !limbo )
delete this;
@ -439,12 +439,12 @@ void Process::ResetAddressSpace()
void Process::GroupRemoveMember(Process* child) // process_family_lock taken
{
assert(child->group == this);
if ( child->groupprev )
child->groupprev->groupnext = child->groupnext;
if ( child->group_prev )
child->group_prev->group_next = child->group_next;
else
groupfirst = child->groupnext;
if ( child->groupnext )
child->groupnext->groupprev = child->groupprev;
group_first = child->group_next;
if ( child->group_next )
child->group_next->group_prev = child->group_prev;
child->group = NULL;
if ( IsLimboDone() )
delete this;
@ -453,17 +453,17 @@ void Process::GroupRemoveMember(Process* child) // process_family_lock taken
void Process::SessionRemoveMember(Process* child) // process_family_lock taken
{
assert(child->session == this);
if ( child->sessionprev )
child->sessionprev->sessionnext = child->sessionnext;
if ( child->session_prev )
child->session_prev->session_next = child->session_next;
else
sessionfirst = child->sessionnext;
if ( child->sessionnext )
child->sessionnext->sessionprev = child->sessionprev;
session_first = child->session_next;
if ( child->session_next )
child->session_next->session_prev = child->session_prev;
child->session = NULL;
if ( !sessionfirst )
if ( !session_first )
{
// Remove reference to tty when session is empty.
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
tty.Reset();
}
if ( IsLimboDone() )
@ -473,12 +473,12 @@ void Process::SessionRemoveMember(Process* child) // process_family_lock taken
void Process::InitRemoveMember(Process* child) // process_family_lock taken
{
assert(child->init == this);
if ( child->initprev )
child->initprev->initnext = child->initnext;
if ( child->init_prev )
child->init_prev->init_next = child->init_next;
else
initfirst = child->initnext;
if ( child->initnext )
child->initnext->initprev = child->initprev;
init_first = child->init_next;
if ( child->init_next )
child->init_next->init_prev = child->init_prev;
child->init = NULL;
if ( IsLimboDone() )
delete this;
@ -486,28 +486,28 @@ void Process::InitRemoveMember(Process* child) // process_family_lock taken
bool Process::IsLimboDone() // process_family_lock taken
{
return limbo && !groupfirst && !sessionfirst && !initfirst;
return limbo && !group_first && !session_first && !init_first;
}
// process_family_lock taken
void Process::NotifyChildExit(Process* child, bool zombify)
{
if ( child->prevsibling )
child->prevsibling->nextsibling = child->nextsibling;
if ( child->nextsibling )
child->nextsibling->prevsibling = child->prevsibling;
if ( firstchild == child )
firstchild = child->nextsibling;
if ( firstchild )
firstchild->prevsibling = NULL;
if ( child->prev_sibling )
child->prev_sibling->next_sibling = child->next_sibling;
if ( child->next_sibling )
child->next_sibling->prev_sibling = child->prev_sibling;
if ( first_child == child )
first_child = child->next_sibling;
if ( first_child )
first_child->prev_sibling = NULL;
if ( zombify )
{
if ( zombiechild )
zombiechild->prevsibling = child;
child->prevsibling = NULL;
child->nextsibling = zombiechild;
zombiechild = child;
if ( zombie_child )
zombie_child->prev_sibling = child;
child->prev_sibling = NULL;
child->next_sibling = zombie_child;
zombie_child = child;
}
// Notify this parent process about the child exiting if it's meant to
@ -516,7 +516,7 @@ void Process::NotifyChildExit(Process* child, bool zombify)
// every child exiting.
DeliverSignal(SIGCHLD);
if ( zombify || is_init_exiting )
kthread_cond_broadcast(&zombiecond);
kthread_cond_broadcast(&zombie_cond);
}
pid_t Process::Wait(pid_t thepid, int* status_ptr, int options)
@ -528,7 +528,7 @@ pid_t Process::Wait(pid_t thepid, int* status_ptr, int options)
ScopedLock lock(&process_family_lock);
// A process can only wait if it has children.
if ( !firstchild && !zombiechild )
if ( !first_child && !zombie_child )
return errno = ECHILD, -1;
// Processes can only wait for their own children to exit.
@ -537,11 +537,11 @@ pid_t Process::Wait(pid_t thepid, int* status_ptr, int options)
// TODO: This is a slow but multithread safe way to verify that the
// target process has the correct parent.
bool found = false;
for ( Process* p = firstchild; !found && p; p = p->nextsibling )
if ( p->pid == thepid && !p->nozombify )
for ( Process* p = first_child; !found && p; p = p->next_sibling )
if ( p->pid == thepid && !p->no_zombify )
found = true;
for ( Process* p = zombiechild; !found && p; p = p->nextsibling )
if ( p->pid == thepid && !p->nozombify )
for ( Process* p = zombie_child; !found && p; p = p->next_sibling )
if ( p->pid == thepid && !p->no_zombify )
found = true;
if ( !found )
return errno = ECHILD, -1;
@ -550,26 +550,26 @@ pid_t Process::Wait(pid_t thepid, int* status_ptr, int options)
Process* zombie = NULL;
while ( !zombie )
{
for ( zombie = zombiechild; zombie; zombie = zombie->nextsibling )
if ( (thepid == -1 || thepid == zombie->pid) && !zombie->nozombify )
for ( zombie = zombie_child; zombie; zombie = zombie->next_sibling )
if ( (thepid == -1 || thepid == zombie->pid) && !zombie->no_zombify )
break;
if ( zombie )
break;
if ( options & WNOHANG )
return 0;
if ( !kthread_cond_wait_signal(&zombiecond, &process_family_lock) )
if ( !kthread_cond_wait_signal(&zombie_cond, &process_family_lock) )
return errno = EINTR, -1;
}
// Remove from the list of zombies.
if ( zombie->prevsibling )
zombie->prevsibling->nextsibling = zombie->nextsibling;
if ( zombie->nextsibling )
zombie->nextsibling->prevsibling = zombie->prevsibling;
if ( zombiechild == zombie )
zombiechild = zombie->nextsibling;
if ( zombiechild )
zombiechild->prevsibling = NULL;
if ( zombie->prev_sibling )
zombie->prev_sibling->next_sibling = zombie->next_sibling;
if ( zombie->next_sibling )
zombie->next_sibling->prev_sibling = zombie->prev_sibling;
if ( zombie_child == zombie )
zombie_child = zombie->next_sibling;
if ( zombie_child )
zombie_child->prev_sibling = NULL;
thepid = zombie->pid;
@ -608,7 +608,7 @@ void Process::ExitThroughSignal(int signal)
void Process::ExitWithCode(int requested_exit_code)
{
ScopedLock lock(&threadlock);
ScopedLock lock(&thread_lock);
if ( exit_code == -1 )
exit_code = requested_exit_code;
@ -616,74 +616,74 @@ void Process::ExitWithCode(int requested_exit_code)
// of process termination. We simply can't stop the threads as they may
// be running in kernel mode doing dangerous stuff. This thread will be
// destroyed by SIGKILL once the system call returns.
for ( Thread* t = firstthread; t; t = t->nextsibling )
for ( Thread* t = first_thread; t; t = t->next_sibling )
t->DeliverSignal(SIGKILL);
}
Ref<MountTable> Process::GetMTable()
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(mtable);
return mtable;
}
Ref<DescriptorTable> Process::GetDTable()
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(dtable);
return dtable;
}
Ref<ProcessTable> Process::GetPTable()
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(ptable);
return ptable;
}
Ref<Descriptor> Process::GetTTY()
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
return tty;
}
Ref<Descriptor> Process::GetRoot()
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(root);
return root;
}
Ref<Descriptor> Process::GetCWD()
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(cwd);
return cwd;
}
void Process::SetTTY(Ref<Descriptor> newtty)
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
tty = newtty;
}
void Process::SetRoot(Ref<Descriptor> newroot)
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(newroot);
root = newroot;
}
void Process::SetCWD(Ref<Descriptor> newcwd)
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(newcwd);
cwd = newcwd;
}
Ref<Descriptor> Process::GetDescriptor(int fd)
{
ScopedLock lock(&ptrlock);
ScopedLock lock(&ptr_lock);
assert(dtable);
return dtable->Get(fd);
}
@ -745,32 +745,32 @@ Process* Process::Fork()
// Remember the relation to the child process.
clone->parent = this;
clone->nextsibling = firstchild;
clone->prevsibling = NULL;
if ( firstchild )
firstchild->prevsibling = clone;
firstchild = clone;
clone->next_sibling = first_child;
clone->prev_sibling = NULL;
if ( first_child )
first_child->prev_sibling = clone;
first_child = clone;
// Add the new process to the current process group.
clone->group = group;
clone->groupprev = NULL;
if ( (clone->groupnext = group->groupfirst) )
group->groupfirst->groupprev = clone;
group->groupfirst = clone;
clone->group_prev = NULL;
if ( (clone->group_next = group->group_first) )
group->group_first->group_prev = clone;
group->group_first = clone;
// Add the new process to the current session.
clone->session = session;
clone->sessionprev = NULL;
if ( (clone->sessionnext = session->sessionfirst) )
session->sessionfirst->sessionprev = clone;
session->sessionfirst = clone;
clone->session_prev = NULL;
if ( (clone->session_next = session->session_first) )
session->session_first->session_prev = clone;
session->session_first = clone;
// Add the new process to the current init.
clone->init = init;
clone->initprev = NULL;
if ( (clone->initnext = init->initfirst) )
init->initfirst->initprev = clone;
init->initfirst = clone;
clone->init_prev = NULL;
if ( (clone->init_next = init->init_first) )
init->init_first->init_prev = clone;
init->init_first = clone;
kthread_mutex_unlock(&process_family_lock);
@ -780,22 +780,22 @@ Process* Process::Fork()
clone->resource_limits[i] = resource_limits[i];
kthread_mutex_unlock(&resource_limits_lock);
kthread_mutex_lock(&nicelock);
kthread_mutex_lock(&nice_lock);
clone->nice = nice;
kthread_mutex_unlock(&nicelock);
kthread_mutex_unlock(&nice_lock);
kthread_mutex_lock(&ptrlock);
kthread_mutex_lock(&ptr_lock);
clone->root = root;
clone->cwd = cwd;
kthread_mutex_unlock(&ptrlock);
kthread_mutex_unlock(&ptr_lock);
kthread_mutex_lock(&idlock);
kthread_mutex_lock(&id_lock);
clone->uid = uid;
clone->gid = gid;
clone->euid = euid;
clone->egid = egid;
clone->umask = umask;
kthread_mutex_unlock(&idlock);
kthread_mutex_unlock(&id_lock);
kthread_mutex_lock(&signal_lock);
memcpy(&clone->signal_actions, &signal_actions, sizeof(signal_actions));
@ -806,13 +806,13 @@ Process* Process::Fork()
// Initialize things that can fail and abort if needed.
bool failure = false;
kthread_mutex_lock(&ptrlock);
kthread_mutex_lock(&ptr_lock);
if ( !(clone->dtable = dtable->Fork()) )
failure = true;
//if ( !(clone->mtable = mtable->Fork()) )
// failure = true;
clone->mtable = mtable;
kthread_mutex_unlock(&ptrlock);
kthread_mutex_unlock(&ptr_lock);
if ( !(clone->program_image_path = String::Clone(program_image_path)) )
failure = true;
@ -1506,13 +1506,13 @@ pid_t sys_tfork(int flags, struct tfork* user_regs)
// TODO: Is it a hack to create a new kernel stack here?
Thread* curthread = CurrentThread();
size_t newkernelstacksize = curthread->kernelstacksize;
uint8_t* newkernelstack = new uint8_t[newkernelstacksize + stack_alignment];
size_t newkernel_stack_size = curthread->kernel_stack_size;
uint8_t* newkernelstack = new uint8_t[newkernel_stack_size + stack_alignment];
if ( !newkernelstack )
return -1;
uintptr_t stack_aligned = (uintptr_t) newkernelstack;
size_t stack_aligned_size = newkernelstacksize;
size_t stack_aligned_size = newkernel_stack_size;
if ( ((uintptr_t) stack_aligned) & (stack_alignment-1) )
stack_aligned = (stack_aligned + 16) & ~(stack_alignment-1);
@ -1594,9 +1594,9 @@ pid_t sys_tfork(int flags, struct tfork* user_regs)
return -1;
}
thread->kernelstackpos = (addr_t) newkernelstack;
thread->kernelstacksize = newkernelstacksize;
thread->kernelstackmalloced = true;
thread->kernel_stack_pos = (addr_t) newkernelstack;
thread->kernel_stack_size = newkernel_stack_size;
thread->kernel_stack_malloced = true;
memcpy(&thread->signal_mask, &regs.sigmask, sizeof(sigset_t));
memcpy(&thread->signal_stack, &regs.altstack, sizeof(stack_t));
@ -1689,13 +1689,13 @@ int sys_setpgid(pid_t pid, pid_t pgid)
return errno = EPERM, -1;
// The process must not be a process group leader.
// TODO: Maybe POSIX actually allows this.
if ( process->groupfirst )
if ( process->group_first )
return errno = EPERM, -1;
// The process must not be a session leader.
if ( process->sessionfirst )
if ( process->session_first )
return errno = EPERM, -1;
// The group must either exist or be the process itself.
if ( !group->groupfirst && group != process )
if ( !group->group_first && group != process )
return errno = EPERM, -1;
// Exit early if this is a noop.
@ -1707,11 +1707,11 @@ int sys_setpgid(pid_t pid, pid_t pgid)
process->group->GroupRemoveMember(process);
// Insert the process into its new process group.
process->groupprev = NULL;
process->groupnext = group->groupfirst;
if ( group->groupfirst )
group->groupfirst->groupprev = process;
group->groupfirst = process;
process->group_prev = NULL;
process->group_next = group->group_first;
if ( group->group_first )
group->group_first->group_prev = process;
group->group_first = process;
process->group = group;
return 0;
@ -1736,15 +1736,15 @@ pid_t sys_setsid(void)
process->session->SessionRemoveMember(process);
// Insert the process into its new session.
process->sessionprev = NULL;
process->sessionnext = NULL;
process->sessionfirst = process;
process->session_prev = NULL;
process->session_next = NULL;
process->session_first = process;
process->session = process;
// Insert the process into its new process group.
process->groupprev = NULL;
process->groupnext = NULL;
process->groupfirst = process;
process->group_prev = NULL;
process->group_next = NULL;
process->group_first = process;
process->group = process;
return process->pid;
@ -1773,21 +1773,21 @@ int sys_setinit(void)
process->init->InitRemoveMember(process);
// Insert the process into its new init.
process->initprev = NULL;
process->initnext = NULL;
process->initfirst = process;
process->init_prev = NULL;
process->init_next = NULL;
process->init_first = process;
process->init = process;
// Insert the process into its new session.
process->sessionprev = NULL;
process->sessionnext = NULL;
process->sessionfirst = process;
process->session_prev = NULL;
process->session_next = NULL;
process->session_first = process;
process->session = process;
// Insert the process into its new process group.
process->groupprev = NULL;
process->groupnext = NULL;
process->groupfirst = process;
process->group_prev = NULL;
process->group_next = NULL;
process->group_first = process;
process->group = process;
return process->pid;
@ -1801,7 +1801,7 @@ size_t sys_getpagesize(void)
mode_t sys_umask(mode_t newmask)
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
mode_t oldmask = process->umask;
process->umask = newmask & 0666;
return oldmask;
@ -1810,7 +1810,7 @@ mode_t sys_umask(mode_t newmask)
mode_t sys_getumask(void)
{
Process* process = CurrentProcess();
ScopedLock lock(&process->idlock);
ScopedLock lock(&process->id_lock);
return process->umask;
}

View file

@ -72,8 +72,8 @@ int sys_psctl(pid_t pid, int request, void* ptr)
{
Process* parent = process->parent;
psst.ppid = parent->pid;
psst.ppid_prev = process->prevsibling ? process->prevsibling->pid : -1;
psst.ppid_next = process->nextsibling ? process->nextsibling->pid : -1;
psst.ppid_prev = process->prev_sibling ? process->prev_sibling->pid : -1;
psst.ppid_next = process->next_sibling ? process->next_sibling->pid : -1;
}
else
{
@ -81,13 +81,13 @@ int sys_psctl(pid_t pid, int request, void* ptr)
psst.ppid_prev = -1;
psst.ppid_next = -1;
}
psst.ppid_first = process->firstchild ? process->firstchild->pid : -1;
psst.ppid_first = process->first_child ? process->first_child->pid : -1;
if ( process->group )
{
Process* group = process->group;
psst.pgid = group->pid;
psst.pgid_prev = process->groupprev ? process->groupprev->pid : -1;
psst.pgid_next = process->groupnext ? process->groupnext->pid : -1;
psst.pgid_prev = process->group_prev ? process->group_prev->pid : -1;
psst.pgid_next = process->group_next ? process->group_next->pid : -1;
}
else
{
@ -95,13 +95,13 @@ int sys_psctl(pid_t pid, int request, void* ptr)
psst.pgid_prev = -1;
psst.pgid_next = -1;
}
psst.pgid_first = process->groupfirst ? process->groupfirst->pid : -1;
psst.pgid_first = process->group_first ? process->group_first->pid : -1;
if ( process->session )
{
Process* session = process->session;
psst.sid = session->pid;
psst.sid_prev = process->sessionprev ? process->sessionprev->pid : -1;
psst.sid_next = process->sessionnext ? process->sessionnext->pid : -1;
psst.sid_prev = process->session_prev ? process->session_prev->pid : -1;
psst.sid_next = process->session_next ? process->session_next->pid : -1;
}
else
{
@ -109,14 +109,14 @@ int sys_psctl(pid_t pid, int request, void* ptr)
psst.sid_prev = -1;
psst.sid_next = -1;
}
psst.sid_first = process->sessionfirst ? process->sessionfirst->pid : -1;
psst.sid_first = process->session_first ? process->session_first->pid : -1;
if ( process->init )
{
Process* init = process->init;
psst.init = init->pid;
psst.init_prev = process->initprev ? process->initprev->pid : -1;
psst.init_next = process->initnext ? process->initnext->pid : -1;
psst.init_prev = process->init_prev ? process->init_prev->pid : -1;
psst.init_next = process->init_next ? process->init_next->pid : -1;
}
else
{
@ -124,19 +124,19 @@ int sys_psctl(pid_t pid, int request, void* ptr)
psst.init_prev = -1;
psst.init_next = -1;
}
psst.init_first = process->initfirst ? process->initfirst->pid : -1;
kthread_mutex_lock(&process->idlock);
psst.init_first = process->init_first ? process->init_first->pid : -1;
kthread_mutex_lock(&process->id_lock);
psst.uid = process->uid;
psst.euid = process->euid;
psst.gid = process->gid;
psst.egid = process->egid;
kthread_mutex_unlock(&process->idlock);
kthread_mutex_lock(&process->threadlock);
kthread_mutex_unlock(&process->id_lock);
kthread_mutex_lock(&process->thread_lock);
psst.status = process->exit_code;
kthread_mutex_unlock(&process->threadlock);
kthread_mutex_lock(&process->nicelock);
kthread_mutex_unlock(&process->thread_lock);
kthread_mutex_lock(&process->nice_lock);
psst.nice = process->nice;
kthread_mutex_unlock(&process->nicelock);
kthread_mutex_unlock(&process->nice_lock);
kthread_mutex_lock(&process->segment_lock);
// TODO: Cache these.
for ( size_t i = 0; i < process->segments_used; i++ )

View file

@ -39,7 +39,7 @@ static int GetProcessPriority(pid_t who)
Process* process = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcess();
if ( !process )
return errno = ESRCH, -1;
ScopedLock lock(&process->nicelock);
ScopedLock lock(&process->nice_lock);
return process->nice;
}
@ -50,7 +50,7 @@ static int SetProcessPriority(pid_t who, int prio)
Process* process = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcess();
if ( !process )
return errno = ESRCH, -1;
ScopedLock lock(&process->nicelock);
ScopedLock lock(&process->nice_lock);
process->nice = prio;
return 0;
}
@ -68,9 +68,9 @@ static int GetProcessGroupPriority(pid_t who)
if ( !group )
return errno = ESRCH, -1;
int lowest = INT_MAX;
for ( Process* process = group->groupfirst; process; process = process->groupnext )
for ( Process* process = group->group_first; process; process = process->group_next )
{
ScopedLock lock(&process->nicelock);
ScopedLock lock(&process->nice_lock);
if ( process->nice < lowest )
lowest = process->nice;
}
@ -84,9 +84,9 @@ static int SetProcessGroupPriority(pid_t who, int prio)
Process* group = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcessGroup();
if ( !group )
return errno = ESRCH, -1;
for ( Process* process = group->groupfirst; process; process = process->groupnext )
for ( Process* process = group->group_first; process; process = process->group_next )
{
ScopedLock lock(&process->nicelock);
ScopedLock lock(&process->nice_lock);
process->nice = prio;
}
return 0;

View file

@ -181,8 +181,8 @@ extern "C" void fake_interrupt(void);
static void FakeInterruptedContext(struct interrupt_context* intctx, int int_no)
{
#if defined(__i386__)
uintptr_t stack = current_thread->kernelstackpos +
current_thread->kernelstacksize;
uintptr_t stack = current_thread->kernel_stack_pos +
current_thread->kernel_stack_size;
stack -= sizeof(struct interrupt_context);
struct interrupt_context* fakectx = (struct interrupt_context*) stack;
memcpy(fakectx, intctx, sizeof(struct interrupt_context));
@ -209,8 +209,8 @@ static void FakeInterruptedContext(struct interrupt_context* intctx, int int_no)
intctx->esp = stack;
intctx->ss = KDS | KRPL;
#elif defined(__x86_64__)
uintptr_t stack = current_thread->kernelstackpos +
current_thread->kernelstacksize;
uintptr_t stack = current_thread->kernel_stack_pos +
current_thread->kernel_stack_size;
stack -= sizeof(struct interrupt_context);
struct interrupt_context* fakectx = (struct interrupt_context*) stack;
memcpy(fakectx, intctx, sizeof(struct interrupt_context));

View file

@ -144,8 +144,8 @@ int sys_sigaction(int signum,
memcpy(kact, &newact, sizeof(struct sigaction));
// Signals may become discarded because of the new handler.
ScopedLock threads_lock(&process->threadlock);
for ( Thread* t = process->firstthread; t; t = t->nextsibling )
ScopedLock threads_lock(&process->thread_lock);
for ( Thread* t = process->first_thread; t; t = t->next_sibling )
UpdatePendingSignals(t);
}
@ -315,9 +315,9 @@ int sys_kill(pid_t pid, int signum)
bool Process::DeliverGroupSignal(int signum) // process_family_lock held
{
if ( !groupfirst )
if ( !group_first )
return errno = ESRCH, false;
for ( Process* iter = groupfirst; iter; iter = iter->groupnext )
for ( Process* iter = group_first; iter; iter = iter->group_next )
{
int saved_errno = errno;
if ( !iter->DeliverSignal(signum) && errno != ESIGPENDING )
@ -331,9 +331,9 @@ bool Process::DeliverGroupSignal(int signum) // process_family_lock held
bool Process::DeliverSessionSignal(int signum) // process_family_lock held
{
if ( !sessionfirst )
if ( !session_first )
return errno = ESRCH, false;
for ( Process* iter = sessionfirst; iter; iter = iter->sessionnext )
for ( Process* iter = session_first; iter; iter = iter->session_next )
{
int saved_errno = errno;
if ( !iter->DeliverSignal(signum) && errno != ESIGPENDING )
@ -347,16 +347,16 @@ bool Process::DeliverSessionSignal(int signum) // process_family_lock held
bool Process::DeliverSignal(int signum)
{
ScopedLock lock(&threadlock);
ScopedLock lock(&thread_lock);
if ( !firstthread )
if ( !first_thread )
return errno = EINIT, false;
// Broadcast particular signals to all the threads in the process.
if ( signum == SIGCONT || signum == SIGSTOP || signum == SIGKILL )
{
int saved_errno = errno;
for ( Thread* t = firstthread; t; t = t->nextsibling )
for ( Thread* t = first_thread; t; t = t->next_sibling )
{
if ( !t->DeliverSignal(signum) && errno != ESIGPENDING )
{
@ -371,7 +371,7 @@ bool Process::DeliverSignal(int signum)
// TODO: This isn't how signals should be routed to a particular thread.
if ( CurrentThread()->process == this )
return CurrentThread()->DeliverSignal(signum);
return firstthread->DeliverSignal(signum);
return first_thread->DeliverSignal(signum);
}
int sys_raise(int signum)

View file

@ -59,18 +59,18 @@ Thread::Thread()
yield_to_tid = 0;
id = 0; // TODO: Make a thread id.
process = NULL;
prevsibling = NULL;
nextsibling = NULL;
prev_sibling = NULL;
next_sibling = NULL;
scheduler_list_prev = NULL;
scheduler_list_next = NULL;
state = NONE;
memset(&registers, 0, sizeof(registers));
kernelstackpos = 0;
kernelstacksize = 0;
kernel_stack_pos = 0;
kernel_stack_size = 0;
signal_count = 0;
signal_single_frame = 0;
signal_canary = 0;
kernelstackmalloced = false;
kernel_stack_malloced = false;
pledged_destruction = false;
force_no_signals = false;
signal_single = false;
@ -99,8 +99,8 @@ Thread::~Thread()
if ( process )
process->OnThreadDestruction(this);
assert(CurrentThread() != this);
if ( kernelstackmalloced )
delete[] (uint8_t*) kernelstackpos;
if ( kernel_stack_malloced )
delete[] (uint8_t*) kernel_stack_pos;
}
Thread* CreateKernelThread(Process* process,
@ -116,7 +116,7 @@ Thread* CreateKernelThread(Process* process,
return errno = EINVAL, (Thread*) NULL;
#endif
kthread_mutex_lock(&process->threadlock);
kthread_mutex_lock(&process->thread_lock);
// Note: Only allow the process itself to make threads, except the initial
// thread. This requirement is because kthread_exit() needs to know when
@ -124,7 +124,7 @@ Thread* CreateKernelThread(Process* process,
// and that no more threads will appear, so it can run some final process
// termination steps without any interference. It's always allowed to create
// threads in the kernel process as it never exits.
assert(!process->firstthread ||
assert(!process->first_thread ||
process == CurrentProcess() ||
process == Scheduler::GetKernelProcess());
@ -137,14 +137,14 @@ Thread* CreateKernelThread(Process* process,
// Create the family tree.
thread->process = process;
Thread* firsty = process->firstthread;
Thread* firsty = process->first_thread;
if ( firsty )
firsty->prevsibling = thread;
thread->nextsibling = firsty;
process->firstthread = thread;
firsty->prev_sibling = thread;
thread->next_sibling = firsty;
process->first_thread = thread;
process->threads_not_exiting_count++;
kthread_mutex_unlock(&process->threadlock);
kthread_mutex_unlock(&process->thread_lock);
return thread;
}
@ -260,9 +260,9 @@ Thread* CreateKernelThread(Process* process, void (*entry)(void*), void* user,
Thread* thread = CreateKernelThread(process, &regs, name);
if ( !thread ) { delete[] stack; return NULL; }
thread->kernelstackpos = (uintptr_t) stack;
thread->kernelstacksize = stacksize;
thread->kernelstackmalloced = true;
thread->kernel_stack_pos = (uintptr_t) stack;
thread->kernel_stack_size = stacksize;
thread->kernel_stack_malloced = true;
return thread;
}
@ -335,11 +335,11 @@ int sys_exit_thread(int requested_exit_code,
extended.unmap_size = Page::AlignUp(extended.unmap_size);
kthread_mutex_lock(&thread->process->threadlock);
kthread_mutex_lock(&thread->process->thread_lock);
bool is_others = false;
for ( Thread* iter = thread->process->firstthread;
for ( Thread* iter = thread->process->first_thread;
!is_others && iter;
iter = iter->nextsibling )
iter = iter->next_sibling )
{
if ( iter == thread )
continue;
@ -355,7 +355,7 @@ int sys_exit_thread(int requested_exit_code,
process->threads_exiting = true;
else if ( process->threads_exiting )
are_threads_exiting = true;
kthread_mutex_unlock(&thread->process->threadlock);
kthread_mutex_unlock(&thread->process->thread_lock);
// Self-destruct if another thread began exiting the process.
if ( are_threads_exiting )

View file

@ -295,7 +295,7 @@ int TTY::tcsetpgrp(ioctx_t* /*ctx*/, pid_t pgid)
Process* process = CurrentProcess()->GetPTable()->Get(pgid);
if ( !process )
return errno = ESRCH, -1;
if ( !process->groupfirst )
if ( !process->group_first )
return errno = EINVAL, -1;
foreground_pgid = pgid;
return 0;
@ -864,7 +864,7 @@ int TTY::ioctl(ioctx_t* ctx, int cmd, uintptr_t arg)
return errno = EPERM, -1;
ScopedLock family_lock(&process_family_lock);
Process* process = CurrentProcess();
if ( !force && !process->sessionfirst )
if ( !force && !process->session_first )
return errno = EPERM, -1;
Process* session = process->session;
// TODO: Don't do this if the sesion already has a tty.

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -14,14 +14,17 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* framebuffer.c
* Framebuffer functions.
* Framebuffer utilities.
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "framebuffer.h"
#include "pixel.h"
#include "vgafont.h"
struct framebuffer framebuffer_crop(struct framebuffer fb,
size_t left,
@ -69,3 +72,102 @@ void framebuffer_copy_to_framebuffer_blend(const struct framebuffer dst,
}
}
}
struct framebuffer framebuffer_crop_int(struct framebuffer fb,
int left,
int top,
int width,
int height)
{
if ( left < 0 ) { width -= -left; left = 0; }
if ( top < 0 ) { top -= -height; top -= 0; }
if ( width < 0 ) { width = 0; }
if ( height < 0 ) { height = 0; }
return framebuffer_crop(fb, left, top, width, height);
}
struct framebuffer framebuffer_cut_left_x(struct framebuffer fb, int offset)
{
fb = framebuffer_crop_int(fb, offset, 0, fb.xres - offset, fb.yres);
return fb;
}
struct framebuffer framebuffer_cut_right_x(struct framebuffer fb, int offset)
{
fb = framebuffer_crop_int(fb, 0, 0, fb.xres - offset, fb.yres);
return fb;
}
struct framebuffer framebuffer_cut_top_y(struct framebuffer fb, int offset)
{
fb = framebuffer_crop_int(fb, 0, offset, fb.xres, fb.yres - offset);
return fb;
}
struct framebuffer framebuffer_cut_bottom_y(struct framebuffer fb, int offset)
{
fb = framebuffer_crop_int(fb, 0, 0, fb.xres, fb.yres - offset);
return fb;
}
struct framebuffer framebuffer_center_x(struct framebuffer fb, int x, int width)
{
x = x - width / 2;
if ( x < 0 ) { width -= -x; x = 0; }
if ( width < 0 ) { width = 0; }
fb = framebuffer_crop(fb, x, 0, width, fb.yres);
return fb;
}
struct framebuffer framebuffer_center_y(struct framebuffer fb, int y, int height)
{
y = y - height / 2;
if ( y < 0 ) { height -= -y; y = 0; }
if ( height < 0 ) { height = 0; }
fb = framebuffer_crop(fb, 0, y, fb.xres, height);
return fb;
}
struct framebuffer framebuffer_right_x(struct framebuffer fb, int x, int width)
{
x = x - width;
if ( x < 0 ) { width -= -x; x = 0; }
if ( width < 0 ) { width = 0; }
fb = framebuffer_crop(fb, x, 0, width, fb.yres);
return fb;
}
struct framebuffer framebuffer_bottom_y(struct framebuffer fb, int y, int height)
{
y = y - height;
if ( y < 0 ) { height -= -y; y = 0; }
if ( height < 0 ) { height = 0; }
fb = framebuffer_crop(fb, 0, y, fb.xres, height);
return fb;
}
struct framebuffer framebuffer_center_text_x(struct framebuffer fb, int x, const char* str)
{
int width = (FONT_WIDTH + 1) * strlen(str);
return framebuffer_center_x(fb, x, width);
}
struct framebuffer framebuffer_center_text_y(struct framebuffer fb, int y, const char* str)
{
(void) str;
int height = FONT_HEIGHT;
return framebuffer_center_y(fb, y, height);
}
struct framebuffer framebuffer_right_text_x(struct framebuffer fb, int x, const char* str)
{
int width = (FONT_WIDTH + 1) * strlen(str);
return framebuffer_right_x(fb, x, width);
}
struct framebuffer framebuffer_bottom_text_y(struct framebuffer fb, int y, const char* str)
{
(void) str;
int height = FONT_HEIGHT;
return framebuffer_bottom_y(fb, y, height);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* framebuffer.h
* Framebuffer functions.
* Framebuffer utilities.
*/
#ifndef FRAMEBUFFER_H
@ -59,5 +59,22 @@ void framebuffer_copy_to_framebuffer(const struct framebuffer dst,
const struct framebuffer src);
void framebuffer_copy_to_framebuffer_blend(const struct framebuffer dst,
const struct framebuffer src);
struct framebuffer framebuffer_crop_int(struct framebuffer fb,
int left,
int top,
int width,
int height);
struct framebuffer framebuffer_cut_left_x(struct framebuffer fb, int offset);
struct framebuffer framebuffer_cut_right_x(struct framebuffer fb, int offset);
struct framebuffer framebuffer_cut_top_y(struct framebuffer fb, int offset);
struct framebuffer framebuffer_cut_bottom_y(struct framebuffer fb, int offset);
struct framebuffer framebuffer_center_x(struct framebuffer fb, int x, int width);
struct framebuffer framebuffer_center_y(struct framebuffer fb, int y, int height);
struct framebuffer framebuffer_right_x(struct framebuffer fb, int x, int width);
struct framebuffer framebuffer_bottom_y(struct framebuffer fb, int y, int height);
struct framebuffer framebuffer_center_text_x(struct framebuffer fb, int x, const char* str);
struct framebuffer framebuffer_center_text_y(struct framebuffer fb, int y, const char* str);
struct framebuffer framebuffer_right_text_x(struct framebuffer fb, int x, const char* str);
struct framebuffer framebuffer_bottom_text_y(struct framebuffer fb, int y, const char* str);
#endif

View file

@ -63,6 +63,7 @@ enum stage
STAGE_USERNAME,
STAGE_PASSWORD,
STAGE_CHECKING,
STAGE_EXITING,
};
struct textbox
@ -111,6 +112,7 @@ struct glogin
enum stage stage;
bool animating;
const char* warning;
const char* announcement;
bool pointer_working;
struct termios old_tio;
bool has_old_tio;
@ -499,6 +501,33 @@ static void render_progress(struct framebuffer fb)
}
}
static void render_exit(struct framebuffer fb)
{
assert(state.announcement);
for ( int yoff = -1; yoff <= 1; yoff++ )
{
for ( int xoff = -1; xoff <= 1; xoff++ )
{
struct framebuffer msgfb = fb;
int y = (fb.yres - FONT_HEIGHT) / 2 + yoff;
msgfb = framebuffer_cut_top_y(msgfb, y);
int w = strlen(state.announcement) * (FONT_WIDTH+1);
int x = (fb.xres - w) / 2 + xoff;
msgfb = framebuffer_cut_left_x(msgfb, x);
render_text(msgfb, state.announcement, make_color_a(0, 0, 0, 64));
}
}
struct framebuffer msgfb = fb;
int y = (fb.yres - FONT_HEIGHT) / 2;
msgfb = framebuffer_cut_top_y(msgfb, y);
int w = strlen(state.announcement) * (FONT_WIDTH+1);
int x = (fb.xres - w) / 2;
msgfb = framebuffer_cut_left_x(msgfb, x);
render_text(msgfb, state.announcement, make_color(255, 255, 255));
}
static void render_login(struct framebuffer fb)
{
render_background(fb);
@ -509,6 +538,7 @@ static void render_login(struct framebuffer fb)
case STAGE_USERNAME: render_form(fb); break;
case STAGE_PASSWORD: render_form(fb); break;
case STAGE_CHECKING: render_progress(fb); break;
case STAGE_EXITING: render_exit(fb); break;
}
if ( state.pointer_working )
render_pointer(fb);
@ -669,6 +699,52 @@ static bool render(struct glogin* state)
return true;
}
static void handle_special_graphical(struct glogin* state,
enum special_action special_action)
{
switch ( special_action )
{
case SPECIAL_ACTION_NONE:
state->announcement = NULL;
break;
case SPECIAL_ACTION_EXIT:
state->announcement = "Exiting...";
break;
case SPECIAL_ACTION_POWEROFF:
state->announcement = "Powering off...";
break;
case SPECIAL_ACTION_REBOOT:
state->announcement = "Rebooting...";
break;
case SPECIAL_ACTION_HALT:
state->announcement = "Halting...";
break;
case SPECIAL_ACTION_REINIT:
state->announcement = "Reinitializing operating system...";
break;
}
if ( state->announcement )
{
state->stage = STAGE_EXITING;
state->fading_from = false;
render(state);
}
handle_special(special_action);
}
static int get_init_exit_plan(void)
{
FILE* fp = popen("/sbin/service default exit-code", "r");
if ( !fp )
return -1;
int result = -1;
char buffer[sizeof(int) * 3];
if ( fgets(buffer, sizeof(buffer), fp) && buffer[0] )
result = atoi(buffer);
pclose(fp);
return result;
}
static void think(struct glogin* state)
{
if ( state->stage == STAGE_CHECKING )
@ -679,6 +755,7 @@ static void think(struct glogin* state)
sched_yield();
return;
}
forward_sigterm_to = 0;
if ( result )
{
if ( !login(username, session) )
@ -696,6 +773,22 @@ static void think(struct glogin* state)
state->warning = strerror(errno);
}
}
// TODO: Find a method to detect what init is trying to do so we can display
// the appropriate message to the user.
if ( got_sigterm )
{
int exit_code = get_init_exit_plan();
enum special_action action = SPECIAL_ACTION_EXIT;
if ( exit_code == 0 )
action = SPECIAL_ACTION_POWEROFF;
else if ( exit_code == 1 )
action = SPECIAL_ACTION_REBOOT;
else if ( exit_code == 2 )
action = SPECIAL_ACTION_HALT;
else if ( exit_code == 3 )
action = SPECIAL_ACTION_REINIT;
handle_special_graphical(state, action);
}
}
static void keyboard_event(struct glogin* state, uint32_t codepoint)
@ -717,7 +810,7 @@ static void keyboard_event(struct glogin* state, uint32_t codepoint)
state->warning = "Invalid username";
break;
}
handle_special(action);
handle_special_graphical(state, action);
state->stage = STAGE_PASSWORD;
textbox_reset(&textbox_password);
break;
@ -729,8 +822,10 @@ static void keyboard_event(struct glogin* state, uint32_t codepoint)
state->stage = STAGE_USERNAME;
state->warning = strerror(errno);
}
forward_sigterm_to = state->chk.pid;
break;
case STAGE_CHECKING:
case STAGE_EXITING:
break;
}
return;
@ -741,6 +836,7 @@ static void keyboard_event(struct glogin* state, uint32_t codepoint)
case STAGE_USERNAME: textbox = &textbox_username; break;
case STAGE_PASSWORD: textbox = &textbox_password; break;
case STAGE_CHECKING: break;
case STAGE_EXITING: break;
}
if ( textbox && codepoint < 128 )
{
@ -871,6 +967,12 @@ bool glogin_init(struct glogin* state)
struct timespec duration = timespec_make(0, 150*1000*1000);
state->fade_from_end = timespec_add(state->fade_from_begin, duration);
}
sigset_t sigterm;
sigemptyset(&sigterm);
sigaddset(&sigterm, SIGTERM);
sigprocmask(SIG_BLOCK, &sigterm, NULL);
struct sigaction sa = { .sa_handler = on_interrupt_signal };
sigaction(SIGTERM, &sa, NULL);
return true;
}
@ -900,9 +1002,14 @@ int glogin_main(struct glogin* state)
nfds_t nfds = 2;
struct timespec wake_now_ts = timespec_make(0, 0);
struct timespec* wake = state->animating ? &wake_now_ts : NULL;
int num_events = ppoll(pfds, nfds, wake, NULL);
sigset_t pollmask;
sigprocmask(SIG_SETMASK, NULL, &pollmask);
sigdelset(&pollmask, SIGTERM);
int num_events = ppoll(pfds, nfds, wake, &pollmask);
if ( num_events < 0 )
{
if ( errno == EINTR )
continue;
warn("poll");
break;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2018, 2022, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2018, 2022, 2023, 2024 Jonas 'Sortie' Termansen.
* Copyright (c) 2023 dzwdz.
*
* Permission to use, copy, modify, and distribute this software for any
@ -46,12 +46,21 @@
#include "login.h"
static void on_interrupt_signal(int signum)
pid_t forward_sigterm_to = 0;
volatile sig_atomic_t got_sigterm = 0;
void on_interrupt_signal(int signum)
{
if ( signum == SIGINT )
dprintf(1, "^C");
if ( signum == SIGQUIT )
dprintf(1, "^\\");
if ( signum == SIGTERM )
{
got_sigterm = 1;
if ( forward_sigterm_to )
kill(forward_sigterm_to, SIGTERM);
}
}
bool check_real(const char* username, const char* password)
@ -112,8 +121,10 @@ bool check_begin(struct check* chk,
{
sigdelset(&chk->oldset, SIGINT);
sigdelset(&chk->oldset, SIGQUIT);
sigdelset(&chk->oldset, SIGTERM);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
unsigned int termmode = TERMMODE_UNICODE | TERMMODE_SIGNAL |
TERMMODE_UTF8 | TERMMODE_LINEBUFFER |
TERMMODE_ECHO;
@ -144,6 +155,17 @@ bool check_end(struct check* chk, bool* result, bool try)
fcntl(chk->pipe, F_SETFL, fcntl(chk->pipe, F_GETFL) | O_NONBLOCK);
chk->pipe_nonblock = true;
}
sigset_t sigterm, oldset;
sigemptyset(&sigterm);
sigaddset(&sigterm, SIGTERM);
struct sigaction sa = { .sa_handler = on_interrupt_signal }, old_sa;
if ( !try )
{
sigprocmask(SIG_BLOCK, &sigterm, &oldset);
forward_sigterm_to = chk->pid;
sigaction(SIGTERM, &sa, &old_sa);
sigprocmask(SIG_UNBLOCK, &sigterm, NULL);
}
while ( chk->errnum_done < sizeof(chk->errnum_bytes) )
{
ssize_t amount = read(chk->pipe, chk->errnum_bytes + chk->errnum_done,
@ -156,6 +178,13 @@ bool check_end(struct check* chk, bool* result, bool try)
}
chk->errnum_done += amount;
}
if ( !try )
{
sigprocmask(SIG_BLOCK, &sigterm, NULL);
forward_sigterm_to = 0;
sigaction(SIGTERM, &old_sa, NULL);
sigprocmask(SIG_SETMASK, &oldset, NULL);
}
int code;
pid_t wait_ret = waitpid(chk->pid, &code, try ? WNOHANG : 0);
if ( try && wait_ret == 0 )
@ -232,9 +261,11 @@ bool login(const char* username, const char* session)
{
sigdelset(&oldset, SIGINT);
sigdelset(&oldset, SIGQUIT);
sigdelset(&oldset, SIGTERM);
sigdelset(&oldset, SIGTSTP);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
(void) (
setpgid(0, 0) < 0 ||
close(pipe_fds[0]) < 0 ||
@ -254,6 +285,7 @@ bool login(const char* username, const char* session)
open("/dev/tty", O_WRONLY) != 2 ||
setcloexecfrom(3) < 0 ||
tcsetpgrp(0, getpgid(0)) ||
// TODO: Do this immediately? At least unblock SIGTERM.
sigprocmask(SIG_SETMASK, &oldset, NULL) < 0 ||
settermmode(0, TERMMODE_NORMAL) < 0 ||
(session ?
@ -269,13 +301,34 @@ bool login(const char* username, const char* session)
}
free(login_shell);
close(pipe_fds[1]);
sigset_t sigterm;
sigemptyset(&sigterm);
sigaddset(&sigterm, SIGTERM);
sigprocmask(SIG_BLOCK, &sigterm, NULL);
struct sigaction sa = { .sa_handler = on_interrupt_signal }, old_sa;
forward_sigterm_to = child_pid;
sigaction(SIGTERM, &sa, &old_sa);
sigprocmask(SIG_UNBLOCK, &sigterm, NULL);
// TODO: What happens if EINTR happens here? waitpid might block.
int errnum;
if ( readall(pipe_fds[0], &errnum, sizeof(errnum)) < (ssize_t) sizeof(errnum) )
errnum = 0;
close(pipe_fds[0]);
int child_status;
if ( waitpid(child_pid, &child_status, 0) < 0 )
while ( waitpid(child_pid, &child_status, 0) < 0 )
{
if ( errno == EINTR )
continue;
errnum = errno;
break;
}
sigprocmask(SIG_BLOCK, &sigterm, NULL);
forward_sigterm_to = 0;
sigaction(SIGTERM, &old_sa, NULL);
tcsetattr(0, TCSAFLUSH, &tio);
tcsetpgrp(0, getpgid(0));
sigprocmask(SIG_SETMASK, &oldset, NULL);
@ -334,7 +387,7 @@ bool parse_username(const char* input,
*session = NULL;
*action = SPECIAL_ACTION_NONE;
if ( !strcmp(input, "exit") )
return *action = SPECIAL_ACTION_POWEROFF, true;
return *action = SPECIAL_ACTION_EXIT, true;
else if ( !strcmp(input, "poweroff") )
return *action = SPECIAL_ACTION_POWEROFF, true;
else if ( !strcmp(input, "reboot") )
@ -376,6 +429,7 @@ void handle_special(enum special_action action)
switch ( action )
{
case SPECIAL_ACTION_NONE: return;
case SPECIAL_ACTION_EXIT: exit(0);
case SPECIAL_ACTION_POWEROFF: exit(0);
case SPECIAL_ACTION_REBOOT: exit(1);
case SPECIAL_ACTION_HALT: exit(2);
@ -394,7 +448,7 @@ int textual(void)
char* username = NULL;
char* session = NULL;
while ( true )
while ( !got_sigterm )
{
char hostname[HOST_NAME_MAX + 1];
hostname[0] = '\0';
@ -460,6 +514,9 @@ int textual(void)
continue;
}
if ( got_sigterm )
break;
if ( !login(username, session) )
{
warn("logging in as %s", username);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2014, 2015, 2023, 2024 Jonas 'Sortie' Termansen.
* Copyright (c) 2023 dzwdz.
*
* Permission to use, copy, modify, and distribute this software for any
@ -39,12 +39,14 @@ struct check
enum special_action
{
SPECIAL_ACTION_NONE,
SPECIAL_ACTION_EXIT,
SPECIAL_ACTION_POWEROFF,
SPECIAL_ACTION_REBOOT,
SPECIAL_ACTION_HALT,
SPECIAL_ACTION_REINIT,
};
void on_interrupt_signal(int signum);
bool login(const char* username, const char* session);
bool check_real(const char* username, const char* password);
bool check_begin(struct check* chk,
@ -62,4 +64,7 @@ bool parse_username(const char* input,
enum special_action* action);
void handle_special(enum special_action action);
extern pid_t forward_sigterm_to;
extern volatile sig_atomic_t got_sigterm;
#endif

10
sh/sh.c
View file

@ -1183,6 +1183,8 @@ struct execute_result execute(char** tokens,
return result;
}
signal(SIGHUP, SIG_DFL);
setpgid(0, pgid != -1 ? pgid : 0);
if ( interactive && pgid == -1 )
{
@ -2042,7 +2044,7 @@ static int run(FILE* fp,
read_command_non_interactive(&sh_read_command, fp);
if ( sh_read_command.abort_condition )
continue;
break;
if ( sh_read_command.eof_condition )
{
@ -2137,6 +2139,9 @@ static int top(FILE* fp,
if ( *script_exited || (status != 0 && exit_on_error) )
return status;
// Receive read EOF instead so we save the shell history.
signal(SIGHUP, SIG_IGN);
edit_line_history_load(&edit_state, getenv("HISTFILE"));
}
@ -2144,7 +2149,10 @@ static int top(FILE* fp,
status);
if ( interactive )
{
edit_line_history_save(&edit_state, getenv("HISTFILE"));
signal(SIGHUP, SIG_DFL);
}
return status;
}