Compare commits
62 commits
c6c285a414
...
cef7779f31
Author | SHA1 | Date | |
---|---|---|---|
|
cef7779f31 | ||
|
36a2d0ccc3 | ||
|
a180902247 | ||
|
5633699695 | ||
|
e3af5ae322 | ||
|
63a6509396 | ||
|
9d287d9433 | ||
|
7eb6a5f517 | ||
|
3cb2bf4590 | ||
|
e88c1ca56c | ||
|
035cd9b1a2 | ||
|
189e79d62d | ||
|
08a834d932 | ||
|
504415bc22 | ||
|
7de016539a | ||
|
bc2cf40dab | ||
|
e76b19fd2b | ||
|
5cec2e2f55 | ||
|
4ba880938e | ||
|
005eb40d27 | ||
|
adb08e530d | ||
|
544b52583e | ||
|
8f879f75a3 | ||
|
e5ae1e62e3 | ||
|
6b158f7795 | ||
|
e74efce270 | ||
|
372370f37d | ||
|
8826615b48 | ||
|
1e2a1f155a | ||
|
257b3abe40 | ||
|
4ea8396b5d | ||
|
0871fa71c3 | ||
|
f9a346a6dc | ||
|
ffafa81cd0 | ||
|
0ab8901f8b | ||
|
8f4c3371f5 | ||
|
e9bfbc8d03 | ||
|
456e2ac596 | ||
|
faff59cffc | ||
|
06fcbdb6ae | ||
|
3fe2a32914 | ||
|
a9b15bffe6 | ||
|
35e68109c9 | ||
|
5248220e40 | ||
|
35f4d2f000 | ||
|
9d317c462e | ||
|
250b95616b | ||
|
204576b7a8 | ||
|
8e3e058fd6 | ||
|
bf2d489da1 | ||
|
d3d339b616 | ||
|
83ac75a083 | ||
|
cc182e7912 | ||
|
d75c716891 | ||
|
704ddbe061 | ||
|
96d4615aee | ||
|
12a69346a0 | ||
|
eede0df814 | ||
|
bab61702f3 | ||
|
bf1d15957e | ||
|
ecd5217da8 | ||
|
735dffd029 |
33 changed files with 791 additions and 355 deletions
|
@ -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ä.
|
* Copyright (c) 2023 Juhani 'nortti' Krekelä.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
@ -149,15 +149,15 @@ CONNECTION_MESSAGE_HANDLER_NO_AUX(shutdown)
|
||||||
{
|
{
|
||||||
(void) connection;
|
(void) connection;
|
||||||
if ( msg->code == 0 )
|
if ( msg->code == 0 )
|
||||||
exit(0);
|
display_exit(server->display, 0);
|
||||||
else if ( msg->code == 1 )
|
else if ( msg->code == 1 )
|
||||||
exit(1);
|
display_exit(server->display, 1);
|
||||||
else if ( msg->code == 2 )
|
else if ( msg->code == 2 )
|
||||||
exit(2);
|
display_exit(server->display, 2);
|
||||||
else if ( msg->code == 3 )
|
else if ( msg->code == 3 )
|
||||||
exit(3);
|
display_exit(server->display, 3);
|
||||||
else
|
else
|
||||||
exit(0);
|
display_exit(server->display, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CONNECTION_MESSAGE_HANDLER_NO_AUX(create_window)
|
CONNECTION_MESSAGE_HANDLER_NO_AUX(create_window)
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <display-protocol.h>
|
#include <display-protocol.h>
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -47,6 +49,43 @@ void display_initialize(struct display* display)
|
||||||
{
|
{
|
||||||
memset(display, 0, sizeof(*display));
|
memset(display, 0, sizeof(*display));
|
||||||
display->redraw = true;
|
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)
|
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)
|
void display_composit(struct display* display, struct framebuffer fb)
|
||||||
{
|
{
|
||||||
struct damage_rect damage_rect = display->damage_rect;
|
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);
|
framebuffer_copy_to_framebuffer(fb, display->wallpaper);
|
||||||
|
|
||||||
|
if ( display->announcement )
|
||||||
|
{
|
||||||
|
display_render_exit(display, fb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for ( struct window* window = display->bottom_window;
|
for ( struct window* window = display->bottom_window;
|
||||||
window;
|
window;
|
||||||
window = window->above_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;
|
case KBKEY_RSUPER: display->key_rsuper = kbkey > 0; break;
|
||||||
}
|
}
|
||||||
if ( display->key_lctrl && display->key_lalt && kbkey == KBKEY_DELETE )
|
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 ( display->key_lctrl && display->key_lalt && kbkey == KBKEY_T )
|
||||||
{
|
{
|
||||||
if ( !fork() )
|
if ( !fork() )
|
||||||
{
|
{
|
||||||
|
sigset_t sigterm;
|
||||||
|
sigemptyset(&sigterm);
|
||||||
|
sigaddset(&sigterm, SIGTERM);
|
||||||
|
sigprocmask(SIG_UNBLOCK, &sigterm, NULL);
|
||||||
execlp("terminal", "terminal", (char*) NULL);
|
execlp("terminal", "terminal", (char*) NULL);
|
||||||
_exit(127);
|
_exit(127);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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);
|
server_mainloop(&server);
|
||||||
|
|
||||||
return 0;
|
return display.exit_code;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -68,14 +68,19 @@ struct display
|
||||||
bool key_rsuper;
|
bool key_rsuper;
|
||||||
bool codepoint_discard;
|
bool codepoint_discard;
|
||||||
bool redraw;
|
bool redraw;
|
||||||
|
bool running;
|
||||||
int pointer_x;
|
int pointer_x;
|
||||||
int pointer_y;
|
int pointer_y;
|
||||||
enum mouse_state mouse_state;
|
enum mouse_state mouse_state;
|
||||||
size_t mouse_byte_count;
|
size_t mouse_byte_count;
|
||||||
uint8_t mouse_bytes[MOUSE_PACKET_SIZE];
|
uint8_t mouse_bytes[MOUSE_PACKET_SIZE];
|
||||||
|
const char* announcement;
|
||||||
|
int exit_code;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void display_initialize(struct display* display);
|
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_list(struct display* display);
|
||||||
void assert_is_well_formed_display(struct display* display);
|
void assert_is_well_formed_display(struct display* display);
|
||||||
void display_link_window_at_top(struct display* display, struct window* window);
|
void display_link_window_at_top(struct display* display, struct window* window);
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -40,6 +41,14 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "vgafont.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)
|
static int open_local_server_socket(const char* path, int flags)
|
||||||
{
|
{
|
||||||
size_t path_length = strlen(path);
|
size_t path_length = strlen(path);
|
||||||
|
@ -196,9 +205,24 @@ void server_poll(struct server* server)
|
||||||
}
|
}
|
||||||
size_t pfds_used = cpfd_off + connections_polled;
|
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 ( num_events < 0 )
|
||||||
|
{
|
||||||
|
if ( errno == EINTR )
|
||||||
|
return;
|
||||||
err(1, "poll");
|
err(1, "poll");
|
||||||
|
}
|
||||||
|
|
||||||
if ( pfds[0].revents )
|
if ( pfds[0].revents )
|
||||||
{
|
{
|
||||||
|
@ -273,9 +297,20 @@ void server_poll(struct server* server)
|
||||||
|
|
||||||
void server_mainloop(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);
|
display_render(server->display);
|
||||||
server_poll(server);
|
server_poll(server);
|
||||||
}
|
}
|
||||||
|
display_render(server->display);
|
||||||
|
|
||||||
|
sigaction(SIGTERM, &old_sa, NULL);
|
||||||
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3256,6 +3256,9 @@ static void init(void)
|
||||||
DAEMON_STATE_FINISHING);
|
DAEMON_STATE_FINISHING);
|
||||||
default_daemon_exit_code =
|
default_daemon_exit_code =
|
||||||
WCONSTRUCT(WNATURE_EXITED, caught_exit_signal, 0);
|
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;
|
caught_exit_signal = -1;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
|
|
||||||
.Sy enable
|
.Sy enable
|
||||||
|
|
|
|
||||||
|
.Sy exit-code
|
||||||
|
|
|
||||||
.Sy kill
|
.Sy kill
|
||||||
|
|
|
|
||||||
.Sy pid
|
.Sy pid
|
||||||
|
@ -177,6 +179,10 @@ command.
|
||||||
The daemon only starts if the
|
The daemon only starts if the
|
||||||
.Ar source-daemon
|
.Ar source-daemon
|
||||||
is running.
|
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
|
.It Sy kill
|
||||||
Kill the
|
Kill the
|
||||||
.Ar daemon
|
.Ar daemon
|
||||||
|
|
|
@ -521,6 +521,8 @@ int main(int argc, char* argv[])
|
||||||
fprintf(fp, "status %s\n", daemon);
|
fprintf(fp, "status %s\n", daemon);
|
||||||
else if ( !strcmp(command, "pid") )
|
else if ( !strcmp(command, "pid") )
|
||||||
fprintf(fp, "status %s\n", daemon);
|
fprintf(fp, "status %s\n", daemon);
|
||||||
|
else if ( !strcmp(command, "exit-code") )
|
||||||
|
fprintf(fp, "status %s\n", daemon);
|
||||||
else if ( !strcmp(command, "requirements") ||
|
else if ( !strcmp(command, "requirements") ||
|
||||||
!strcmp(command, "dependents") ||
|
!strcmp(command, "dependents") ||
|
||||||
!strcmp(command, "edges") )
|
!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") ||
|
else if ( !strcmp(command, "requirements") ||
|
||||||
!strcmp(command, "dependents") ||
|
!strcmp(command, "dependents") ||
|
||||||
!strcmp(command, "edges") )
|
!strcmp(command, "edges") )
|
||||||
|
|
|
@ -250,6 +250,7 @@ int DevCOMPort::ioctl(ioctx_t* ctx, int cmd, uintptr_t arg)
|
||||||
const struct winsize* user_ws = (const struct winsize*) arg;
|
const struct winsize* user_ws = (const struct winsize*) arg;
|
||||||
if ( !ctx->copy_from_src(&ws, user_ws, sizeof(ws)) )
|
if ( !ctx->copy_from_src(&ws, user_ws, sizeof(ws)) )
|
||||||
return -1;
|
return -1;
|
||||||
|
winch();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lock.Reset();
|
lock.Reset();
|
||||||
|
|
|
@ -679,9 +679,9 @@ Ref<Descriptor> Descriptor::open(ioctx_t* ctx, const char* filename, int flags,
|
||||||
mode_t mode)
|
mode_t mode)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
kthread_mutex_lock(&process->idlock);
|
kthread_mutex_lock(&process->id_lock);
|
||||||
mode &= ~process->umask;
|
mode &= ~process->umask;
|
||||||
kthread_mutex_unlock(&process->idlock);
|
kthread_mutex_unlock(&process->id_lock);
|
||||||
|
|
||||||
if ( !filename[0] )
|
if ( !filename[0] )
|
||||||
return errno = ENOENT, Ref<Descriptor>();
|
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)
|
int Descriptor::mkdir(ioctx_t* ctx, const char* filename, mode_t mode)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
kthread_mutex_lock(&process->idlock);
|
kthread_mutex_lock(&process->id_lock);
|
||||||
mode &= ~process->umask;
|
mode &= ~process->umask;
|
||||||
kthread_mutex_unlock(&process->idlock);
|
kthread_mutex_unlock(&process->id_lock);
|
||||||
|
|
||||||
char* final;
|
char* final;
|
||||||
Ref<Descriptor> dir = OpenDirContainingPath(ctx, Ref<Descriptor>(this),
|
Ref<Descriptor> dir = OpenDirContainingPath(ctx, Ref<Descriptor>(this),
|
||||||
|
|
|
@ -29,14 +29,14 @@ namespace Sortix {
|
||||||
uid_t sys_getuid()
|
uid_t sys_getuid()
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
return process->uid;
|
return process->uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_setuid(uid_t uid)
|
int sys_setuid(uid_t uid)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
// TODO: Implement security checks in many place across the operating system
|
// 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.
|
// and until then allow anyone to do this to not pretend to be secure.
|
||||||
process->uid = uid;
|
process->uid = uid;
|
||||||
|
@ -47,14 +47,14 @@ int sys_setuid(uid_t uid)
|
||||||
gid_t sys_getgid()
|
gid_t sys_getgid()
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
return process->gid;
|
return process->gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_setgid(gid_t gid)
|
int sys_setgid(gid_t gid)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
// TODO: Implement security checks in many place across the operating system
|
// 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.
|
// and until then allow anyone to do this to not pretend to be secure.
|
||||||
process->gid = gid;
|
process->gid = gid;
|
||||||
|
@ -65,14 +65,14 @@ int sys_setgid(gid_t gid)
|
||||||
uid_t sys_geteuid()
|
uid_t sys_geteuid()
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
return process->euid;
|
return process->euid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_seteuid(uid_t euid)
|
int sys_seteuid(uid_t euid)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
// TODO: Implement security checks in many place across the operating system
|
// 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.
|
// and until then allow anyone to do this to not pretend to be secure.
|
||||||
process->euid = euid;
|
process->euid = euid;
|
||||||
|
@ -82,14 +82,14 @@ int sys_seteuid(uid_t euid)
|
||||||
gid_t sys_getegid()
|
gid_t sys_getegid()
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
return process->egid;
|
return process->egid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_setegid(gid_t egid)
|
int sys_setegid(gid_t egid)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
// TODO: Implement security checks in many place across the operating system
|
// 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.
|
// and until then allow anyone to do this to not pretend to be secure.
|
||||||
process->egid = egid;
|
process->egid = egid;
|
||||||
|
|
|
@ -66,17 +66,17 @@ public:
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
kthread_mutex_t nicelock;
|
kthread_mutex_t nice_lock;
|
||||||
int nice;
|
int nice;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
kthread_mutex_t idlock;
|
kthread_mutex_t id_lock;
|
||||||
uid_t uid, euid;
|
uid_t uid, euid;
|
||||||
gid_t gid, egid;
|
gid_t gid, egid;
|
||||||
mode_t umask;
|
mode_t umask;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
kthread_mutex_t ptrlock;
|
kthread_mutex_t ptr_lock;
|
||||||
Ref<Descriptor> tty;
|
Ref<Descriptor> tty;
|
||||||
Ref<Descriptor> root;
|
Ref<Descriptor> root;
|
||||||
Ref<Descriptor> cwd;
|
Ref<Descriptor> cwd;
|
||||||
|
@ -112,34 +112,34 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Process* parent;
|
Process* parent;
|
||||||
Process* prevsibling;
|
Process* prev_sibling;
|
||||||
Process* nextsibling;
|
Process* next_sibling;
|
||||||
Process* firstchild;
|
Process* first_child;
|
||||||
Process* zombiechild;
|
Process* zombie_child;
|
||||||
Process* group;
|
Process* group;
|
||||||
Process* groupprev;
|
Process* group_prev;
|
||||||
Process* groupnext;
|
Process* group_next;
|
||||||
Process* groupfirst;
|
Process* group_first;
|
||||||
Process* session;
|
Process* session;
|
||||||
Process* sessionprev;
|
Process* session_prev;
|
||||||
Process* sessionnext;
|
Process* session_next;
|
||||||
Process* sessionfirst;
|
Process* session_first;
|
||||||
Process* init;
|
Process* init;
|
||||||
Process* initprev;
|
Process* init_prev;
|
||||||
Process* initnext;
|
Process* init_next;
|
||||||
Process* initfirst;
|
Process* init_first;
|
||||||
kthread_mutex_t childlock;
|
kthread_mutex_t child_lock;
|
||||||
kthread_mutex_t parentlock;
|
kthread_mutex_t parent_lock;
|
||||||
kthread_cond_t zombiecond;
|
kthread_cond_t zombie_cond;
|
||||||
bool iszombie;
|
bool is_zombie;
|
||||||
bool nozombify;
|
bool no_zombify;
|
||||||
bool limbo;
|
bool limbo;
|
||||||
bool is_init_exiting;
|
bool is_init_exiting;
|
||||||
int exit_code;
|
int exit_code;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Thread* firstthread;
|
Thread* first_thread;
|
||||||
kthread_mutex_t threadlock;
|
kthread_mutex_t thread_lock;
|
||||||
size_t threads_not_exiting_count;
|
size_t threads_not_exiting_count;
|
||||||
bool threads_exiting;
|
bool threads_exiting;
|
||||||
|
|
||||||
|
|
|
@ -79,8 +79,8 @@ public:
|
||||||
struct thread_registers registers;
|
struct thread_registers registers;
|
||||||
size_t id;
|
size_t id;
|
||||||
Process* process;
|
Process* process;
|
||||||
Thread* prevsibling;
|
Thread* prev_sibling;
|
||||||
Thread* nextsibling;
|
Thread* next_sibling;
|
||||||
Thread* scheduler_list_prev;
|
Thread* scheduler_list_prev;
|
||||||
Thread* scheduler_list_next;
|
Thread* scheduler_list_next;
|
||||||
volatile ThreadState state;
|
volatile ThreadState state;
|
||||||
|
@ -88,12 +88,12 @@ public:
|
||||||
sigset_t signal_mask;
|
sigset_t signal_mask;
|
||||||
sigset_t saved_signal_mask;
|
sigset_t saved_signal_mask;
|
||||||
stack_t signal_stack;
|
stack_t signal_stack;
|
||||||
addr_t kernelstackpos;
|
addr_t kernel_stack_pos;
|
||||||
size_t kernelstacksize;
|
size_t kernel_stack_size;
|
||||||
size_t signal_count;
|
size_t signal_count;
|
||||||
uintptr_t signal_single_frame;
|
uintptr_t signal_single_frame;
|
||||||
uintptr_t signal_canary;
|
uintptr_t signal_canary;
|
||||||
bool kernelstackmalloced;
|
bool kernel_stack_malloced;
|
||||||
bool pledged_destruction;
|
bool pledged_destruction;
|
||||||
bool force_no_signals;
|
bool force_no_signals;
|
||||||
bool signal_single;
|
bool signal_single;
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace Sortix {
|
||||||
void SetupUserIOCtx(ioctx_t* ctx)
|
void SetupUserIOCtx(ioctx_t* ctx)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
ctx->uid = ctx->auth_uid = process->uid;
|
ctx->uid = ctx->auth_uid = process->uid;
|
||||||
ctx->gid = ctx->auth_gid = process->gid;
|
ctx->gid = ctx->auth_gid = process->gid;
|
||||||
ctx->copy_to_dest = CopyToUser;
|
ctx->copy_to_dest = CopyToUser;
|
||||||
|
@ -39,7 +39,7 @@ void SetupUserIOCtx(ioctx_t* ctx)
|
||||||
void SetupKernelIOCtx(ioctx_t* ctx)
|
void SetupKernelIOCtx(ioctx_t* ctx)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
ctx->uid = ctx->auth_uid = process->uid;
|
ctx->uid = ctx->auth_uid = process->uid;
|
||||||
ctx->gid = ctx->auth_gid = process->gid;
|
ctx->gid = ctx->auth_gid = process->gid;
|
||||||
ctx->copy_to_dest = CopyToKernel;
|
ctx->copy_to_dest = CopyToKernel;
|
||||||
|
|
|
@ -374,17 +374,17 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
|
||||||
ptable.Reset();
|
ptable.Reset();
|
||||||
system->addrspace = Memory::GetAddressSpace();
|
system->addrspace = Memory::GetAddressSpace();
|
||||||
system->group = system;
|
system->group = system;
|
||||||
system->groupprev = NULL;
|
system->group_prev = NULL;
|
||||||
system->groupnext = NULL;
|
system->group_next = NULL;
|
||||||
system->groupfirst = system;
|
system->group_first = system;
|
||||||
system->session = system;
|
system->session = system;
|
||||||
system->sessionprev = NULL;
|
system->session_prev = NULL;
|
||||||
system->sessionnext = NULL;
|
system->session_next = NULL;
|
||||||
system->sessionfirst = system;
|
system->session_first = system;
|
||||||
system->init = NULL;
|
system->init = NULL;
|
||||||
system->initprev = NULL;
|
system->init_prev = NULL;
|
||||||
system->initnext = NULL;
|
system->init_next = NULL;
|
||||||
system->initfirst = NULL;
|
system->init_first = NULL;
|
||||||
|
|
||||||
if ( !(system->program_image_path = String::Clone("<kernel process>")) )
|
if ( !(system->program_image_path = String::Clone("<kernel process>")) )
|
||||||
Panic("Unable to clone string for system process name");
|
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();
|
Thread* idlethread = new Thread();
|
||||||
idlethread->name = "idle";
|
idlethread->name = "idle";
|
||||||
idlethread->process = system;
|
idlethread->process = system;
|
||||||
idlethread->kernelstackpos = (addr_t) stack;
|
idlethread->kernel_stack_pos = (addr_t) stack;
|
||||||
idlethread->kernelstacksize = STACK_SIZE;
|
idlethread->kernel_stack_size = STACK_SIZE;
|
||||||
idlethread->kernelstackmalloced = false;
|
idlethread->kernel_stack_malloced = false;
|
||||||
system->firstthread = idlethread;
|
system->first_thread = idlethread;
|
||||||
system->threads_not_exiting_count = 1;
|
system->threads_not_exiting_count = 1;
|
||||||
Scheduler::SetIdleThread(idlethread);
|
Scheduler::SetIdleThread(idlethread);
|
||||||
|
|
||||||
|
@ -667,23 +667,23 @@ static void BootThread(void* /*user*/)
|
||||||
kthread_mutex_lock(&process_family_lock);
|
kthread_mutex_lock(&process_family_lock);
|
||||||
Process* kernel_process = CurrentProcess();
|
Process* kernel_process = CurrentProcess();
|
||||||
init->parent = kernel_process;
|
init->parent = kernel_process;
|
||||||
init->nextsibling = kernel_process->firstchild;
|
init->next_sibling = kernel_process->first_child;
|
||||||
init->prevsibling = NULL;
|
init->prev_sibling = NULL;
|
||||||
if ( kernel_process->firstchild )
|
if ( kernel_process->first_child )
|
||||||
kernel_process->firstchild->prevsibling = init;
|
kernel_process->first_child->prev_sibling = init;
|
||||||
kernel_process->firstchild = init;
|
kernel_process->first_child = init;
|
||||||
init->group = init;
|
init->group = init;
|
||||||
init->groupprev = NULL;
|
init->group_prev = NULL;
|
||||||
init->groupnext = NULL;
|
init->group_next = NULL;
|
||||||
init->groupfirst = init;
|
init->group_first = init;
|
||||||
init->session = init;
|
init->session = init;
|
||||||
init->sessionprev = NULL;
|
init->session_prev = NULL;
|
||||||
init->sessionnext = NULL;
|
init->session_next = NULL;
|
||||||
init->sessionfirst = init;
|
init->session_first = init;
|
||||||
init->init = init;
|
init->init = init;
|
||||||
init->initprev = NULL;
|
init->init_prev = NULL;
|
||||||
init->initnext = NULL;
|
init->init_next = NULL;
|
||||||
init->initfirst = init;
|
init->init_first = init;
|
||||||
kthread_mutex_unlock(&process_family_lock);
|
kthread_mutex_unlock(&process_family_lock);
|
||||||
|
|
||||||
// TODO: Why don't we fork from pid=0 and this is done for us?
|
// TODO: Why don't we fork from pid=0 and this is done for us?
|
||||||
|
|
|
@ -258,9 +258,9 @@ void kthread_exit()
|
||||||
// only threads in this process, except the initial thread. Otherwise more
|
// 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
|
// threads may appear, and we can't conclude whether this is the last thread
|
||||||
// in the process to exit.
|
// 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;
|
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
|
// 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
|
// 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
|
// below code that schedules thread termination. It's therefore safe to run
|
||||||
|
|
|
@ -202,10 +202,10 @@ PingSocket::PingSocket(int af)
|
||||||
dev = (dev_t) this;
|
dev = (dev_t) this;
|
||||||
ino = (ino_t) this;
|
ino = (ino_t) this;
|
||||||
type = S_IFSOCK;
|
type = S_IFSOCK;
|
||||||
kthread_mutex_lock(&process->idlock);
|
kthread_mutex_lock(&process->id_lock);
|
||||||
stat_uid = process->uid;
|
stat_uid = process->uid;
|
||||||
stat_gid = process->gid;
|
stat_gid = process->gid;
|
||||||
kthread_mutex_unlock(&process->idlock);
|
kthread_mutex_unlock(&process->id_lock);
|
||||||
stat_mode = 0600 | this->type;
|
stat_mode = 0600 | this->type;
|
||||||
supports_iovec = true;
|
supports_iovec = true;
|
||||||
socket_lock = KTHREAD_MUTEX_INITIALIZER;
|
socket_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
|
@ -2417,10 +2417,10 @@ TCPSocketNode::TCPSocketNode(TCPSocket* socket)
|
||||||
dev = (dev_t) this;
|
dev = (dev_t) this;
|
||||||
ino = (ino_t) this;
|
ino = (ino_t) this;
|
||||||
type = S_IFSOCK;
|
type = S_IFSOCK;
|
||||||
kthread_mutex_lock(&process->idlock);
|
kthread_mutex_lock(&process->id_lock);
|
||||||
stat_uid = process->uid;
|
stat_uid = process->uid;
|
||||||
stat_gid = process->gid;
|
stat_gid = process->gid;
|
||||||
kthread_mutex_unlock(&process->idlock);
|
kthread_mutex_unlock(&process->id_lock);
|
||||||
stat_mode = 0600 | this->type;
|
stat_mode = 0600 | this->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,10 +175,10 @@ UDPSocket::UDPSocket(int af)
|
||||||
dev = (dev_t) this;
|
dev = (dev_t) this;
|
||||||
ino = (ino_t) this;
|
ino = (ino_t) this;
|
||||||
type = S_IFSOCK;
|
type = S_IFSOCK;
|
||||||
kthread_mutex_lock(&process->idlock);
|
kthread_mutex_lock(&process->id_lock);
|
||||||
stat_uid = process->uid;
|
stat_uid = process->uid;
|
||||||
stat_gid = process->gid;
|
stat_gid = process->gid;
|
||||||
kthread_mutex_unlock(&process->idlock);
|
kthread_mutex_unlock(&process->id_lock);
|
||||||
stat_mode = 0600 | this->type;
|
stat_mode = 0600 | this->type;
|
||||||
supports_iovec = true;
|
supports_iovec = true;
|
||||||
socket_lock = KTHREAD_MUTEX_INITIALIZER;
|
socket_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
|
@ -79,15 +79,15 @@ Process::Process()
|
||||||
addrspace = 0;
|
addrspace = 0;
|
||||||
pid = 0;
|
pid = 0;
|
||||||
|
|
||||||
nicelock = KTHREAD_MUTEX_INITIALIZER;
|
nice_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
nice = 0;
|
nice = 0;
|
||||||
|
|
||||||
idlock = KTHREAD_MUTEX_INITIALIZER;
|
id_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
uid = euid = 0;
|
uid = euid = 0;
|
||||||
gid = egid = 0;
|
gid = egid = 0;
|
||||||
umask = 0022;
|
umask = 0022;
|
||||||
|
|
||||||
ptrlock = KTHREAD_MUTEX_INITIALIZER;
|
ptr_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
// tty set to null reference in the member constructor.
|
// tty set to null reference in the member constructor.
|
||||||
// root 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.
|
// cwd set to null reference in the member constructor.
|
||||||
|
@ -116,31 +116,31 @@ Process::Process()
|
||||||
sigreturn = NULL;
|
sigreturn = NULL;
|
||||||
|
|
||||||
parent = NULL;
|
parent = NULL;
|
||||||
prevsibling = NULL;
|
prev_sibling = NULL;
|
||||||
nextsibling = NULL;
|
next_sibling = NULL;
|
||||||
firstchild = NULL;
|
first_child = NULL;
|
||||||
zombiechild = NULL;
|
zombie_child = NULL;
|
||||||
group = NULL;
|
group = NULL;
|
||||||
groupprev = NULL;
|
group_prev = NULL;
|
||||||
groupnext = NULL;
|
group_next = NULL;
|
||||||
groupfirst = NULL;
|
group_first = NULL;
|
||||||
session = NULL;
|
session = NULL;
|
||||||
sessionprev = NULL;
|
session_prev = NULL;
|
||||||
sessionnext = NULL;
|
session_next = NULL;
|
||||||
sessionfirst = NULL;
|
session_first = NULL;
|
||||||
init = NULL;
|
init = NULL;
|
||||||
initprev = NULL;
|
init_prev = NULL;
|
||||||
initnext = NULL;
|
init_next = NULL;
|
||||||
initfirst = NULL;
|
init_first = NULL;
|
||||||
zombiecond = KTHREAD_COND_INITIALIZER;
|
zombie_cond = KTHREAD_COND_INITIALIZER;
|
||||||
iszombie = false;
|
is_zombie = false;
|
||||||
nozombify = false;
|
no_zombify = false;
|
||||||
limbo = false;
|
limbo = false;
|
||||||
is_init_exiting = false;
|
is_init_exiting = false;
|
||||||
exit_code = -1;
|
exit_code = -1;
|
||||||
|
|
||||||
firstthread = NULL;
|
first_thread = NULL;
|
||||||
threadlock = KTHREAD_MUTEX_INITIALIZER;
|
thread_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
threads_not_exiting_count = 0;
|
threads_not_exiting_count = 0;
|
||||||
threads_exiting = false;
|
threads_exiting = false;
|
||||||
|
|
||||||
|
@ -170,15 +170,15 @@ Process::~Process() // process_family_lock taken
|
||||||
if ( alarm_timer.IsAttached() )
|
if ( alarm_timer.IsAttached() )
|
||||||
alarm_timer.Detach();
|
alarm_timer.Detach();
|
||||||
delete[] program_image_path;
|
delete[] program_image_path;
|
||||||
assert(!zombiechild);
|
assert(!zombie_child);
|
||||||
assert(!init);
|
assert(!init);
|
||||||
assert(!session);
|
assert(!session);
|
||||||
assert(!group);
|
assert(!group);
|
||||||
assert(!parent);
|
assert(!parent);
|
||||||
assert(!initfirst);
|
assert(!init_first);
|
||||||
assert(!sessionfirst);
|
assert(!session_first);
|
||||||
assert(!groupfirst);
|
assert(!group_first);
|
||||||
assert(!firstchild);
|
assert(!first_child);
|
||||||
assert(!addrspace);
|
assert(!addrspace);
|
||||||
assert(!segments);
|
assert(!segments);
|
||||||
assert(!dtable);
|
assert(!dtable);
|
||||||
|
@ -195,7 +195,7 @@ Process::~Process() // process_family_lock taken
|
||||||
|
|
||||||
void Process::BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtable)
|
void Process::BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtable)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(!this->dtable);
|
assert(!this->dtable);
|
||||||
assert(!this->mtable);
|
assert(!this->mtable);
|
||||||
this->dtable = dtable;
|
this->dtable = dtable;
|
||||||
|
@ -204,7 +204,7 @@ void Process::BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtabl
|
||||||
|
|
||||||
void Process::BootstrapDirectories(Ref<Descriptor> root)
|
void Process::BootstrapDirectories(Ref<Descriptor> root)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(!this->root);
|
assert(!this->root);
|
||||||
assert(!this->cwd);
|
assert(!this->cwd);
|
||||||
this->root = root;
|
this->root = root;
|
||||||
|
@ -223,43 +223,43 @@ void Process::OnLastThreadExit()
|
||||||
// Forbid any more processes and threads from being created, so this
|
// Forbid any more processes and threads from being created, so this
|
||||||
// loop will always terminate.
|
// loop will always terminate.
|
||||||
is_init_exiting = true;
|
is_init_exiting = true;
|
||||||
Process* process = firstchild;
|
Process* process = first_child;
|
||||||
while ( process )
|
while ( process )
|
||||||
{
|
{
|
||||||
if ( process->pid != 0 )
|
if ( process->pid != 0 )
|
||||||
process->DeliverSignal(SIGKILL);
|
process->DeliverSignal(SIGKILL);
|
||||||
if ( process->init == process )
|
if ( process->init == process )
|
||||||
process->is_init_exiting = true;
|
process->is_init_exiting = true;
|
||||||
if ( process->firstchild )
|
if ( process->first_child )
|
||||||
process = process->firstchild;
|
process = process->first_child;
|
||||||
while ( process && process != this && !process->nextsibling )
|
while ( process && process != this && !process->next_sibling )
|
||||||
process = process->parent;
|
process = process->parent;
|
||||||
if ( process == this )
|
if ( process == this )
|
||||||
break;
|
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.
|
// is_init_exiting is true.
|
||||||
while ( firstchild )
|
while ( first_child )
|
||||||
kthread_cond_wait(&zombiecond, &process_family_lock);
|
kthread_cond_wait(&zombie_cond, &process_family_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::OnThreadDestruction(Thread* thread)
|
void Process::OnThreadDestruction(Thread* thread)
|
||||||
{
|
{
|
||||||
assert(thread->process == this);
|
assert(thread->process == this);
|
||||||
kthread_mutex_lock(&threadlock);
|
kthread_mutex_lock(&thread_lock);
|
||||||
if ( thread->prevsibling )
|
if ( thread->prev_sibling )
|
||||||
thread->prevsibling->nextsibling = thread->nextsibling;
|
thread->prev_sibling->next_sibling = thread->next_sibling;
|
||||||
if ( thread->nextsibling )
|
if ( thread->next_sibling )
|
||||||
thread->nextsibling->prevsibling = thread->prevsibling;
|
thread->next_sibling->prev_sibling = thread->prev_sibling;
|
||||||
if ( thread == firstthread )
|
if ( thread == first_thread )
|
||||||
firstthread = thread->nextsibling;
|
first_thread = thread->next_sibling;
|
||||||
if ( firstthread )
|
if ( first_thread )
|
||||||
firstthread->prevsibling = NULL;
|
first_thread->prev_sibling = NULL;
|
||||||
thread->prevsibling = thread->nextsibling = NULL;
|
thread->prev_sibling = thread->next_sibling = NULL;
|
||||||
bool threadsleft = firstthread;
|
bool threadsleft = first_thread;
|
||||||
kthread_mutex_unlock(&threadlock);
|
kthread_mutex_unlock(&thread_lock);
|
||||||
|
|
||||||
// We are called from the threads destructor, let it finish before we
|
// We are called from the threads destructor, let it finish before we
|
||||||
// we handle the situation by killing ourselves.
|
// we handle the situation by killing ourselves.
|
||||||
|
@ -275,7 +275,7 @@ void Process__AfterLastThreadExit(void* user)
|
||||||
void Process::ScheduleDeath()
|
void Process::ScheduleDeath()
|
||||||
{
|
{
|
||||||
// All our threads must have exited at this point.
|
// All our threads must have exited at this point.
|
||||||
assert(!firstthread);
|
assert(!first_thread);
|
||||||
Worker::Schedule(Process__AfterLastThreadExit, this);
|
Worker::Schedule(Process__AfterLastThreadExit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ void Process::ScheduleDeath()
|
||||||
// process after this call as another thread may garbage collect it.
|
// process after this call as another thread may garbage collect it.
|
||||||
void Process::AbortConstruction()
|
void Process::AbortConstruction()
|
||||||
{
|
{
|
||||||
nozombify = true;
|
no_zombify = true;
|
||||||
ScheduleDeath();
|
ScheduleDeath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ void Process::LastPrayer()
|
||||||
{
|
{
|
||||||
assert(this);
|
assert(this);
|
||||||
// This must never be called twice.
|
// This must never be called twice.
|
||||||
assert(!iszombie);
|
assert(!is_zombie);
|
||||||
|
|
||||||
// This must be called from a thread using another address space as the
|
// This must be called from a thread using another address space as the
|
||||||
// address space of this process is about to be destroyed.
|
// address space of this process is about to be destroyed.
|
||||||
|
@ -319,7 +319,7 @@ void Process::LastPrayer()
|
||||||
assert(curthread->process != this);
|
assert(curthread->process != this);
|
||||||
|
|
||||||
// This can't be called if the process is still alive.
|
// 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.
|
// Disarm and detach all the timers in the process.
|
||||||
DeleteTimers();
|
DeleteTimers();
|
||||||
|
@ -348,7 +348,7 @@ void Process::LastPrayer()
|
||||||
|
|
||||||
ScopedLock family_lock(&process_family_lock);
|
ScopedLock family_lock(&process_family_lock);
|
||||||
|
|
||||||
iszombie = true;
|
is_zombie = true;
|
||||||
|
|
||||||
// Init is nice and will gladly raise our orphaned children and zombies.
|
// Init is nice and will gladly raise our orphaned children and zombies.
|
||||||
// Child processes can't be reparented away if we're init. OnLastThreadExit
|
// Child processes can't be reparented away if we're init. OnLastThreadExit
|
||||||
|
@ -358,33 +358,33 @@ void Process::LastPrayer()
|
||||||
if ( init == this )
|
if ( init == this )
|
||||||
{
|
{
|
||||||
assert(is_init_exiting);
|
assert(is_init_exiting);
|
||||||
assert(!firstchild);
|
assert(!first_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( firstchild )
|
while ( first_child )
|
||||||
{
|
{
|
||||||
Process* process = firstchild;
|
Process* process = first_child;
|
||||||
firstchild = process->nextsibling;
|
first_child = process->next_sibling;
|
||||||
process->parent = init;
|
process->parent = init;
|
||||||
process->prevsibling = NULL;
|
process->prev_sibling = NULL;
|
||||||
process->nextsibling = init->firstchild;
|
process->next_sibling = init->first_child;
|
||||||
if ( init->firstchild )
|
if ( init->first_child )
|
||||||
init->firstchild->prevsibling = process;
|
init->first_child->prev_sibling = process;
|
||||||
init->firstchild = process;
|
init->first_child = process;
|
||||||
process->nozombify = true;
|
process->no_zombify = true;
|
||||||
}
|
}
|
||||||
// Since we have no more children (they are with init now), we don't
|
// 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
|
// 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.
|
// applies on process termination.
|
||||||
while ( zombiechild )
|
while ( zombie_child )
|
||||||
{
|
{
|
||||||
Process* zombie = zombiechild;
|
Process* zombie = zombie_child;
|
||||||
zombiechild = zombie->nextsibling;
|
zombie_child = zombie->next_sibling;
|
||||||
zombie->nextsibling = NULL;
|
zombie->next_sibling = NULL;
|
||||||
if ( zombiechild )
|
if ( zombie_child )
|
||||||
zombiechild->prevsibling = NULL;
|
zombie_child->prev_sibling = NULL;
|
||||||
zombie->nozombify = true;
|
zombie->no_zombify = true;
|
||||||
zombie->WaitedFor();
|
zombie->WaitedFor();
|
||||||
}
|
}
|
||||||
// Remove ourself from our process group.
|
// Remove ourself from our process group.
|
||||||
|
@ -397,7 +397,7 @@ void Process::LastPrayer()
|
||||||
if ( init )
|
if ( init )
|
||||||
init->InitRemoveMember(this);
|
init->InitRemoveMember(this);
|
||||||
|
|
||||||
bool zombify = !nozombify;
|
bool zombify = !no_zombify;
|
||||||
|
|
||||||
// This class instance will be destroyed by our parent process when it
|
// This class instance will be destroyed by our parent process when it
|
||||||
// has received and acknowledged our death.
|
// has received and acknowledged our death.
|
||||||
|
@ -413,7 +413,7 @@ void Process::WaitedFor() // process_family_lock taken
|
||||||
{
|
{
|
||||||
parent = NULL;
|
parent = NULL;
|
||||||
limbo = false;
|
limbo = false;
|
||||||
if ( groupfirst || sessionfirst || initfirst )
|
if ( group_first || session_first || init_first )
|
||||||
limbo = true;
|
limbo = true;
|
||||||
if ( !limbo )
|
if ( !limbo )
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -439,12 +439,12 @@ void Process::ResetAddressSpace()
|
||||||
void Process::GroupRemoveMember(Process* child) // process_family_lock taken
|
void Process::GroupRemoveMember(Process* child) // process_family_lock taken
|
||||||
{
|
{
|
||||||
assert(child->group == this);
|
assert(child->group == this);
|
||||||
if ( child->groupprev )
|
if ( child->group_prev )
|
||||||
child->groupprev->groupnext = child->groupnext;
|
child->group_prev->group_next = child->group_next;
|
||||||
else
|
else
|
||||||
groupfirst = child->groupnext;
|
group_first = child->group_next;
|
||||||
if ( child->groupnext )
|
if ( child->group_next )
|
||||||
child->groupnext->groupprev = child->groupprev;
|
child->group_next->group_prev = child->group_prev;
|
||||||
child->group = NULL;
|
child->group = NULL;
|
||||||
if ( IsLimboDone() )
|
if ( IsLimboDone() )
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -453,17 +453,17 @@ void Process::GroupRemoveMember(Process* child) // process_family_lock taken
|
||||||
void Process::SessionRemoveMember(Process* child) // process_family_lock taken
|
void Process::SessionRemoveMember(Process* child) // process_family_lock taken
|
||||||
{
|
{
|
||||||
assert(child->session == this);
|
assert(child->session == this);
|
||||||
if ( child->sessionprev )
|
if ( child->session_prev )
|
||||||
child->sessionprev->sessionnext = child->sessionnext;
|
child->session_prev->session_next = child->session_next;
|
||||||
else
|
else
|
||||||
sessionfirst = child->sessionnext;
|
session_first = child->session_next;
|
||||||
if ( child->sessionnext )
|
if ( child->session_next )
|
||||||
child->sessionnext->sessionprev = child->sessionprev;
|
child->session_next->session_prev = child->session_prev;
|
||||||
child->session = NULL;
|
child->session = NULL;
|
||||||
if ( !sessionfirst )
|
if ( !session_first )
|
||||||
{
|
{
|
||||||
// Remove reference to tty when session is empty.
|
// Remove reference to tty when session is empty.
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
tty.Reset();
|
tty.Reset();
|
||||||
}
|
}
|
||||||
if ( IsLimboDone() )
|
if ( IsLimboDone() )
|
||||||
|
@ -473,12 +473,12 @@ void Process::SessionRemoveMember(Process* child) // process_family_lock taken
|
||||||
void Process::InitRemoveMember(Process* child) // process_family_lock taken
|
void Process::InitRemoveMember(Process* child) // process_family_lock taken
|
||||||
{
|
{
|
||||||
assert(child->init == this);
|
assert(child->init == this);
|
||||||
if ( child->initprev )
|
if ( child->init_prev )
|
||||||
child->initprev->initnext = child->initnext;
|
child->init_prev->init_next = child->init_next;
|
||||||
else
|
else
|
||||||
initfirst = child->initnext;
|
init_first = child->init_next;
|
||||||
if ( child->initnext )
|
if ( child->init_next )
|
||||||
child->initnext->initprev = child->initprev;
|
child->init_next->init_prev = child->init_prev;
|
||||||
child->init = NULL;
|
child->init = NULL;
|
||||||
if ( IsLimboDone() )
|
if ( IsLimboDone() )
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -486,28 +486,28 @@ void Process::InitRemoveMember(Process* child) // process_family_lock taken
|
||||||
|
|
||||||
bool Process::IsLimboDone() // 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
|
// process_family_lock taken
|
||||||
void Process::NotifyChildExit(Process* child, bool zombify)
|
void Process::NotifyChildExit(Process* child, bool zombify)
|
||||||
{
|
{
|
||||||
if ( child->prevsibling )
|
if ( child->prev_sibling )
|
||||||
child->prevsibling->nextsibling = child->nextsibling;
|
child->prev_sibling->next_sibling = child->next_sibling;
|
||||||
if ( child->nextsibling )
|
if ( child->next_sibling )
|
||||||
child->nextsibling->prevsibling = child->prevsibling;
|
child->next_sibling->prev_sibling = child->prev_sibling;
|
||||||
if ( firstchild == child )
|
if ( first_child == child )
|
||||||
firstchild = child->nextsibling;
|
first_child = child->next_sibling;
|
||||||
if ( firstchild )
|
if ( first_child )
|
||||||
firstchild->prevsibling = NULL;
|
first_child->prev_sibling = NULL;
|
||||||
|
|
||||||
if ( zombify )
|
if ( zombify )
|
||||||
{
|
{
|
||||||
if ( zombiechild )
|
if ( zombie_child )
|
||||||
zombiechild->prevsibling = child;
|
zombie_child->prev_sibling = child;
|
||||||
child->prevsibling = NULL;
|
child->prev_sibling = NULL;
|
||||||
child->nextsibling = zombiechild;
|
child->next_sibling = zombie_child;
|
||||||
zombiechild = child;
|
zombie_child = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify this parent process about the child exiting if it's meant to
|
// 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.
|
// every child exiting.
|
||||||
DeliverSignal(SIGCHLD);
|
DeliverSignal(SIGCHLD);
|
||||||
if ( zombify || is_init_exiting )
|
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)
|
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);
|
ScopedLock lock(&process_family_lock);
|
||||||
|
|
||||||
// A process can only wait if it has children.
|
// A process can only wait if it has children.
|
||||||
if ( !firstchild && !zombiechild )
|
if ( !first_child && !zombie_child )
|
||||||
return errno = ECHILD, -1;
|
return errno = ECHILD, -1;
|
||||||
|
|
||||||
// Processes can only wait for their own children to exit.
|
// 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
|
// TODO: This is a slow but multithread safe way to verify that the
|
||||||
// target process has the correct parent.
|
// target process has the correct parent.
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for ( Process* p = firstchild; !found && p; p = p->nextsibling )
|
for ( Process* p = first_child; !found && p; p = p->next_sibling )
|
||||||
if ( p->pid == thepid && !p->nozombify )
|
if ( p->pid == thepid && !p->no_zombify )
|
||||||
found = true;
|
found = true;
|
||||||
for ( Process* p = zombiechild; !found && p; p = p->nextsibling )
|
for ( Process* p = zombie_child; !found && p; p = p->next_sibling )
|
||||||
if ( p->pid == thepid && !p->nozombify )
|
if ( p->pid == thepid && !p->no_zombify )
|
||||||
found = true;
|
found = true;
|
||||||
if ( !found )
|
if ( !found )
|
||||||
return errno = ECHILD, -1;
|
return errno = ECHILD, -1;
|
||||||
|
@ -550,26 +550,26 @@ pid_t Process::Wait(pid_t thepid, int* status_ptr, int options)
|
||||||
Process* zombie = NULL;
|
Process* zombie = NULL;
|
||||||
while ( !zombie )
|
while ( !zombie )
|
||||||
{
|
{
|
||||||
for ( zombie = zombiechild; zombie; zombie = zombie->nextsibling )
|
for ( zombie = zombie_child; zombie; zombie = zombie->next_sibling )
|
||||||
if ( (thepid == -1 || thepid == zombie->pid) && !zombie->nozombify )
|
if ( (thepid == -1 || thepid == zombie->pid) && !zombie->no_zombify )
|
||||||
break;
|
break;
|
||||||
if ( zombie )
|
if ( zombie )
|
||||||
break;
|
break;
|
||||||
if ( options & WNOHANG )
|
if ( options & WNOHANG )
|
||||||
return 0;
|
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;
|
return errno = EINTR, -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from the list of zombies.
|
// Remove from the list of zombies.
|
||||||
if ( zombie->prevsibling )
|
if ( zombie->prev_sibling )
|
||||||
zombie->prevsibling->nextsibling = zombie->nextsibling;
|
zombie->prev_sibling->next_sibling = zombie->next_sibling;
|
||||||
if ( zombie->nextsibling )
|
if ( zombie->next_sibling )
|
||||||
zombie->nextsibling->prevsibling = zombie->prevsibling;
|
zombie->next_sibling->prev_sibling = zombie->prev_sibling;
|
||||||
if ( zombiechild == zombie )
|
if ( zombie_child == zombie )
|
||||||
zombiechild = zombie->nextsibling;
|
zombie_child = zombie->next_sibling;
|
||||||
if ( zombiechild )
|
if ( zombie_child )
|
||||||
zombiechild->prevsibling = NULL;
|
zombie_child->prev_sibling = NULL;
|
||||||
|
|
||||||
thepid = zombie->pid;
|
thepid = zombie->pid;
|
||||||
|
|
||||||
|
@ -608,7 +608,7 @@ void Process::ExitThroughSignal(int signal)
|
||||||
|
|
||||||
void Process::ExitWithCode(int requested_exit_code)
|
void Process::ExitWithCode(int requested_exit_code)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&threadlock);
|
ScopedLock lock(&thread_lock);
|
||||||
if ( exit_code == -1 )
|
if ( exit_code == -1 )
|
||||||
exit_code = requested_exit_code;
|
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
|
// 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
|
// be running in kernel mode doing dangerous stuff. This thread will be
|
||||||
// destroyed by SIGKILL once the system call returns.
|
// 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);
|
t->DeliverSignal(SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<MountTable> Process::GetMTable()
|
Ref<MountTable> Process::GetMTable()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(mtable);
|
assert(mtable);
|
||||||
return mtable;
|
return mtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<DescriptorTable> Process::GetDTable()
|
Ref<DescriptorTable> Process::GetDTable()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(dtable);
|
assert(dtable);
|
||||||
return dtable;
|
return dtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<ProcessTable> Process::GetPTable()
|
Ref<ProcessTable> Process::GetPTable()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(ptable);
|
assert(ptable);
|
||||||
return ptable;
|
return ptable;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Descriptor> Process::GetTTY()
|
Ref<Descriptor> Process::GetTTY()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
return tty;
|
return tty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Descriptor> Process::GetRoot()
|
Ref<Descriptor> Process::GetRoot()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(root);
|
assert(root);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Descriptor> Process::GetCWD()
|
Ref<Descriptor> Process::GetCWD()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(cwd);
|
assert(cwd);
|
||||||
return cwd;
|
return cwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::SetTTY(Ref<Descriptor> newtty)
|
void Process::SetTTY(Ref<Descriptor> newtty)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
tty = newtty;
|
tty = newtty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::SetRoot(Ref<Descriptor> newroot)
|
void Process::SetRoot(Ref<Descriptor> newroot)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(newroot);
|
assert(newroot);
|
||||||
root = newroot;
|
root = newroot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::SetCWD(Ref<Descriptor> newcwd)
|
void Process::SetCWD(Ref<Descriptor> newcwd)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(newcwd);
|
assert(newcwd);
|
||||||
cwd = newcwd;
|
cwd = newcwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Descriptor> Process::GetDescriptor(int fd)
|
Ref<Descriptor> Process::GetDescriptor(int fd)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptr_lock);
|
||||||
assert(dtable);
|
assert(dtable);
|
||||||
return dtable->Get(fd);
|
return dtable->Get(fd);
|
||||||
}
|
}
|
||||||
|
@ -745,32 +745,32 @@ Process* Process::Fork()
|
||||||
|
|
||||||
// Remember the relation to the child process.
|
// Remember the relation to the child process.
|
||||||
clone->parent = this;
|
clone->parent = this;
|
||||||
clone->nextsibling = firstchild;
|
clone->next_sibling = first_child;
|
||||||
clone->prevsibling = NULL;
|
clone->prev_sibling = NULL;
|
||||||
if ( firstchild )
|
if ( first_child )
|
||||||
firstchild->prevsibling = clone;
|
first_child->prev_sibling = clone;
|
||||||
firstchild = clone;
|
first_child = clone;
|
||||||
|
|
||||||
// Add the new process to the current process group.
|
// Add the new process to the current process group.
|
||||||
clone->group = group;
|
clone->group = group;
|
||||||
clone->groupprev = NULL;
|
clone->group_prev = NULL;
|
||||||
if ( (clone->groupnext = group->groupfirst) )
|
if ( (clone->group_next = group->group_first) )
|
||||||
group->groupfirst->groupprev = clone;
|
group->group_first->group_prev = clone;
|
||||||
group->groupfirst = clone;
|
group->group_first = clone;
|
||||||
|
|
||||||
// Add the new process to the current session.
|
// Add the new process to the current session.
|
||||||
clone->session = session;
|
clone->session = session;
|
||||||
clone->sessionprev = NULL;
|
clone->session_prev = NULL;
|
||||||
if ( (clone->sessionnext = session->sessionfirst) )
|
if ( (clone->session_next = session->session_first) )
|
||||||
session->sessionfirst->sessionprev = clone;
|
session->session_first->session_prev = clone;
|
||||||
session->sessionfirst = clone;
|
session->session_first = clone;
|
||||||
|
|
||||||
// Add the new process to the current init.
|
// Add the new process to the current init.
|
||||||
clone->init = init;
|
clone->init = init;
|
||||||
clone->initprev = NULL;
|
clone->init_prev = NULL;
|
||||||
if ( (clone->initnext = init->initfirst) )
|
if ( (clone->init_next = init->init_first) )
|
||||||
init->initfirst->initprev = clone;
|
init->init_first->init_prev = clone;
|
||||||
init->initfirst = clone;
|
init->init_first = clone;
|
||||||
|
|
||||||
kthread_mutex_unlock(&process_family_lock);
|
kthread_mutex_unlock(&process_family_lock);
|
||||||
|
|
||||||
|
@ -780,22 +780,22 @@ Process* Process::Fork()
|
||||||
clone->resource_limits[i] = resource_limits[i];
|
clone->resource_limits[i] = resource_limits[i];
|
||||||
kthread_mutex_unlock(&resource_limits_lock);
|
kthread_mutex_unlock(&resource_limits_lock);
|
||||||
|
|
||||||
kthread_mutex_lock(&nicelock);
|
kthread_mutex_lock(&nice_lock);
|
||||||
clone->nice = nice;
|
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->root = root;
|
||||||
clone->cwd = cwd;
|
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->uid = uid;
|
||||||
clone->gid = gid;
|
clone->gid = gid;
|
||||||
clone->euid = euid;
|
clone->euid = euid;
|
||||||
clone->egid = egid;
|
clone->egid = egid;
|
||||||
clone->umask = umask;
|
clone->umask = umask;
|
||||||
kthread_mutex_unlock(&idlock);
|
kthread_mutex_unlock(&id_lock);
|
||||||
|
|
||||||
kthread_mutex_lock(&signal_lock);
|
kthread_mutex_lock(&signal_lock);
|
||||||
memcpy(&clone->signal_actions, &signal_actions, sizeof(signal_actions));
|
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.
|
// Initialize things that can fail and abort if needed.
|
||||||
bool failure = false;
|
bool failure = false;
|
||||||
|
|
||||||
kthread_mutex_lock(&ptrlock);
|
kthread_mutex_lock(&ptr_lock);
|
||||||
if ( !(clone->dtable = dtable->Fork()) )
|
if ( !(clone->dtable = dtable->Fork()) )
|
||||||
failure = true;
|
failure = true;
|
||||||
//if ( !(clone->mtable = mtable->Fork()) )
|
//if ( !(clone->mtable = mtable->Fork()) )
|
||||||
// failure = true;
|
// failure = true;
|
||||||
clone->mtable = mtable;
|
clone->mtable = mtable;
|
||||||
kthread_mutex_unlock(&ptrlock);
|
kthread_mutex_unlock(&ptr_lock);
|
||||||
|
|
||||||
if ( !(clone->program_image_path = String::Clone(program_image_path)) )
|
if ( !(clone->program_image_path = String::Clone(program_image_path)) )
|
||||||
failure = true;
|
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?
|
// TODO: Is it a hack to create a new kernel stack here?
|
||||||
Thread* curthread = CurrentThread();
|
Thread* curthread = CurrentThread();
|
||||||
size_t newkernelstacksize = curthread->kernelstacksize;
|
size_t newkernel_stack_size = curthread->kernel_stack_size;
|
||||||
uint8_t* newkernelstack = new uint8_t[newkernelstacksize + stack_alignment];
|
uint8_t* newkernelstack = new uint8_t[newkernel_stack_size + stack_alignment];
|
||||||
if ( !newkernelstack )
|
if ( !newkernelstack )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
uintptr_t stack_aligned = (uintptr_t) newkernelstack;
|
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) )
|
if ( ((uintptr_t) stack_aligned) & (stack_alignment-1) )
|
||||||
stack_aligned = (stack_aligned + 16) & ~(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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->kernelstackpos = (addr_t) newkernelstack;
|
thread->kernel_stack_pos = (addr_t) newkernelstack;
|
||||||
thread->kernelstacksize = newkernelstacksize;
|
thread->kernel_stack_size = newkernel_stack_size;
|
||||||
thread->kernelstackmalloced = true;
|
thread->kernel_stack_malloced = true;
|
||||||
memcpy(&thread->signal_mask, ®s.sigmask, sizeof(sigset_t));
|
memcpy(&thread->signal_mask, ®s.sigmask, sizeof(sigset_t));
|
||||||
memcpy(&thread->signal_stack, ®s.altstack, sizeof(stack_t));
|
memcpy(&thread->signal_stack, ®s.altstack, sizeof(stack_t));
|
||||||
|
|
||||||
|
@ -1689,13 +1689,13 @@ int sys_setpgid(pid_t pid, pid_t pgid)
|
||||||
return errno = EPERM, -1;
|
return errno = EPERM, -1;
|
||||||
// The process must not be a process group leader.
|
// The process must not be a process group leader.
|
||||||
// TODO: Maybe POSIX actually allows this.
|
// TODO: Maybe POSIX actually allows this.
|
||||||
if ( process->groupfirst )
|
if ( process->group_first )
|
||||||
return errno = EPERM, -1;
|
return errno = EPERM, -1;
|
||||||
// The process must not be a session leader.
|
// The process must not be a session leader.
|
||||||
if ( process->sessionfirst )
|
if ( process->session_first )
|
||||||
return errno = EPERM, -1;
|
return errno = EPERM, -1;
|
||||||
// The group must either exist or be the process itself.
|
// 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;
|
return errno = EPERM, -1;
|
||||||
|
|
||||||
// Exit early if this is a noop.
|
// Exit early if this is a noop.
|
||||||
|
@ -1707,11 +1707,11 @@ int sys_setpgid(pid_t pid, pid_t pgid)
|
||||||
process->group->GroupRemoveMember(process);
|
process->group->GroupRemoveMember(process);
|
||||||
|
|
||||||
// Insert the process into its new process group.
|
// Insert the process into its new process group.
|
||||||
process->groupprev = NULL;
|
process->group_prev = NULL;
|
||||||
process->groupnext = group->groupfirst;
|
process->group_next = group->group_first;
|
||||||
if ( group->groupfirst )
|
if ( group->group_first )
|
||||||
group->groupfirst->groupprev = process;
|
group->group_first->group_prev = process;
|
||||||
group->groupfirst = process;
|
group->group_first = process;
|
||||||
process->group = group;
|
process->group = group;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1736,15 +1736,15 @@ pid_t sys_setsid(void)
|
||||||
process->session->SessionRemoveMember(process);
|
process->session->SessionRemoveMember(process);
|
||||||
|
|
||||||
// Insert the process into its new session.
|
// Insert the process into its new session.
|
||||||
process->sessionprev = NULL;
|
process->session_prev = NULL;
|
||||||
process->sessionnext = NULL;
|
process->session_next = NULL;
|
||||||
process->sessionfirst = process;
|
process->session_first = process;
|
||||||
process->session = process;
|
process->session = process;
|
||||||
|
|
||||||
// Insert the process into its new process group.
|
// Insert the process into its new process group.
|
||||||
process->groupprev = NULL;
|
process->group_prev = NULL;
|
||||||
process->groupnext = NULL;
|
process->group_next = NULL;
|
||||||
process->groupfirst = process;
|
process->group_first = process;
|
||||||
process->group = process;
|
process->group = process;
|
||||||
|
|
||||||
return process->pid;
|
return process->pid;
|
||||||
|
@ -1773,21 +1773,21 @@ int sys_setinit(void)
|
||||||
process->init->InitRemoveMember(process);
|
process->init->InitRemoveMember(process);
|
||||||
|
|
||||||
// Insert the process into its new init.
|
// Insert the process into its new init.
|
||||||
process->initprev = NULL;
|
process->init_prev = NULL;
|
||||||
process->initnext = NULL;
|
process->init_next = NULL;
|
||||||
process->initfirst = process;
|
process->init_first = process;
|
||||||
process->init = process;
|
process->init = process;
|
||||||
|
|
||||||
// Insert the process into its new session.
|
// Insert the process into its new session.
|
||||||
process->sessionprev = NULL;
|
process->session_prev = NULL;
|
||||||
process->sessionnext = NULL;
|
process->session_next = NULL;
|
||||||
process->sessionfirst = process;
|
process->session_first = process;
|
||||||
process->session = process;
|
process->session = process;
|
||||||
|
|
||||||
// Insert the process into its new process group.
|
// Insert the process into its new process group.
|
||||||
process->groupprev = NULL;
|
process->group_prev = NULL;
|
||||||
process->groupnext = NULL;
|
process->group_next = NULL;
|
||||||
process->groupfirst = process;
|
process->group_first = process;
|
||||||
process->group = process;
|
process->group = process;
|
||||||
|
|
||||||
return process->pid;
|
return process->pid;
|
||||||
|
@ -1801,7 +1801,7 @@ size_t sys_getpagesize(void)
|
||||||
mode_t sys_umask(mode_t newmask)
|
mode_t sys_umask(mode_t newmask)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
mode_t oldmask = process->umask;
|
mode_t oldmask = process->umask;
|
||||||
process->umask = newmask & 0666;
|
process->umask = newmask & 0666;
|
||||||
return oldmask;
|
return oldmask;
|
||||||
|
@ -1810,7 +1810,7 @@ mode_t sys_umask(mode_t newmask)
|
||||||
mode_t sys_getumask(void)
|
mode_t sys_getumask(void)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->id_lock);
|
||||||
return process->umask;
|
return process->umask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,8 @@ int sys_psctl(pid_t pid, int request, void* ptr)
|
||||||
{
|
{
|
||||||
Process* parent = process->parent;
|
Process* parent = process->parent;
|
||||||
psst.ppid = parent->pid;
|
psst.ppid = parent->pid;
|
||||||
psst.ppid_prev = process->prevsibling ? process->prevsibling->pid : -1;
|
psst.ppid_prev = process->prev_sibling ? process->prev_sibling->pid : -1;
|
||||||
psst.ppid_next = process->nextsibling ? process->nextsibling->pid : -1;
|
psst.ppid_next = process->next_sibling ? process->next_sibling->pid : -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -81,13 +81,13 @@ int sys_psctl(pid_t pid, int request, void* ptr)
|
||||||
psst.ppid_prev = -1;
|
psst.ppid_prev = -1;
|
||||||
psst.ppid_next = -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 )
|
if ( process->group )
|
||||||
{
|
{
|
||||||
Process* group = process->group;
|
Process* group = process->group;
|
||||||
psst.pgid = group->pid;
|
psst.pgid = group->pid;
|
||||||
psst.pgid_prev = process->groupprev ? process->groupprev->pid : -1;
|
psst.pgid_prev = process->group_prev ? process->group_prev->pid : -1;
|
||||||
psst.pgid_next = process->groupnext ? process->groupnext->pid : -1;
|
psst.pgid_next = process->group_next ? process->group_next->pid : -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -95,13 +95,13 @@ int sys_psctl(pid_t pid, int request, void* ptr)
|
||||||
psst.pgid_prev = -1;
|
psst.pgid_prev = -1;
|
||||||
psst.pgid_next = -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 )
|
if ( process->session )
|
||||||
{
|
{
|
||||||
Process* session = process->session;
|
Process* session = process->session;
|
||||||
psst.sid = session->pid;
|
psst.sid = session->pid;
|
||||||
psst.sid_prev = process->sessionprev ? process->sessionprev->pid : -1;
|
psst.sid_prev = process->session_prev ? process->session_prev->pid : -1;
|
||||||
psst.sid_next = process->sessionnext ? process->sessionnext->pid : -1;
|
psst.sid_next = process->session_next ? process->session_next->pid : -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -109,14 +109,14 @@ int sys_psctl(pid_t pid, int request, void* ptr)
|
||||||
psst.sid_prev = -1;
|
psst.sid_prev = -1;
|
||||||
psst.sid_next = -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 )
|
if ( process->init )
|
||||||
{
|
{
|
||||||
Process* init = process->init;
|
Process* init = process->init;
|
||||||
psst.init = init->pid;
|
psst.init = init->pid;
|
||||||
psst.init_prev = process->initprev ? process->initprev->pid : -1;
|
psst.init_prev = process->init_prev ? process->init_prev->pid : -1;
|
||||||
psst.init_next = process->initnext ? process->initnext->pid : -1;
|
psst.init_next = process->init_next ? process->init_next->pid : -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -124,19 +124,19 @@ int sys_psctl(pid_t pid, int request, void* ptr)
|
||||||
psst.init_prev = -1;
|
psst.init_prev = -1;
|
||||||
psst.init_next = -1;
|
psst.init_next = -1;
|
||||||
}
|
}
|
||||||
psst.init_first = process->initfirst ? process->initfirst->pid : -1;
|
psst.init_first = process->init_first ? process->init_first->pid : -1;
|
||||||
kthread_mutex_lock(&process->idlock);
|
kthread_mutex_lock(&process->id_lock);
|
||||||
psst.uid = process->uid;
|
psst.uid = process->uid;
|
||||||
psst.euid = process->euid;
|
psst.euid = process->euid;
|
||||||
psst.gid = process->gid;
|
psst.gid = process->gid;
|
||||||
psst.egid = process->egid;
|
psst.egid = process->egid;
|
||||||
kthread_mutex_unlock(&process->idlock);
|
kthread_mutex_unlock(&process->id_lock);
|
||||||
kthread_mutex_lock(&process->threadlock);
|
kthread_mutex_lock(&process->thread_lock);
|
||||||
psst.status = process->exit_code;
|
psst.status = process->exit_code;
|
||||||
kthread_mutex_unlock(&process->threadlock);
|
kthread_mutex_unlock(&process->thread_lock);
|
||||||
kthread_mutex_lock(&process->nicelock);
|
kthread_mutex_lock(&process->nice_lock);
|
||||||
psst.nice = process->nice;
|
psst.nice = process->nice;
|
||||||
kthread_mutex_unlock(&process->nicelock);
|
kthread_mutex_unlock(&process->nice_lock);
|
||||||
kthread_mutex_lock(&process->segment_lock);
|
kthread_mutex_lock(&process->segment_lock);
|
||||||
// TODO: Cache these.
|
// TODO: Cache these.
|
||||||
for ( size_t i = 0; i < process->segments_used; i++ )
|
for ( size_t i = 0; i < process->segments_used; i++ )
|
||||||
|
|
|
@ -39,7 +39,7 @@ static int GetProcessPriority(pid_t who)
|
||||||
Process* process = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcess();
|
Process* process = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcess();
|
||||||
if ( !process )
|
if ( !process )
|
||||||
return errno = ESRCH, -1;
|
return errno = ESRCH, -1;
|
||||||
ScopedLock lock(&process->nicelock);
|
ScopedLock lock(&process->nice_lock);
|
||||||
return process->nice;
|
return process->nice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ static int SetProcessPriority(pid_t who, int prio)
|
||||||
Process* process = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcess();
|
Process* process = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcess();
|
||||||
if ( !process )
|
if ( !process )
|
||||||
return errno = ESRCH, -1;
|
return errno = ESRCH, -1;
|
||||||
ScopedLock lock(&process->nicelock);
|
ScopedLock lock(&process->nice_lock);
|
||||||
process->nice = prio;
|
process->nice = prio;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,9 @@ static int GetProcessGroupPriority(pid_t who)
|
||||||
if ( !group )
|
if ( !group )
|
||||||
return errno = ESRCH, -1;
|
return errno = ESRCH, -1;
|
||||||
int lowest = INT_MAX;
|
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 )
|
if ( process->nice < lowest )
|
||||||
lowest = process->nice;
|
lowest = process->nice;
|
||||||
}
|
}
|
||||||
|
@ -84,9 +84,9 @@ static int SetProcessGroupPriority(pid_t who, int prio)
|
||||||
Process* group = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcessGroup();
|
Process* group = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcessGroup();
|
||||||
if ( !group )
|
if ( !group )
|
||||||
return errno = ESRCH, -1;
|
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;
|
process->nice = prio;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -181,8 +181,8 @@ extern "C" void fake_interrupt(void);
|
||||||
static void FakeInterruptedContext(struct interrupt_context* intctx, int int_no)
|
static void FakeInterruptedContext(struct interrupt_context* intctx, int int_no)
|
||||||
{
|
{
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
uintptr_t stack = current_thread->kernelstackpos +
|
uintptr_t stack = current_thread->kernel_stack_pos +
|
||||||
current_thread->kernelstacksize;
|
current_thread->kernel_stack_size;
|
||||||
stack -= sizeof(struct interrupt_context);
|
stack -= sizeof(struct interrupt_context);
|
||||||
struct interrupt_context* fakectx = (struct interrupt_context*) stack;
|
struct interrupt_context* fakectx = (struct interrupt_context*) stack;
|
||||||
memcpy(fakectx, intctx, sizeof(struct interrupt_context));
|
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->esp = stack;
|
||||||
intctx->ss = KDS | KRPL;
|
intctx->ss = KDS | KRPL;
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
uintptr_t stack = current_thread->kernelstackpos +
|
uintptr_t stack = current_thread->kernel_stack_pos +
|
||||||
current_thread->kernelstacksize;
|
current_thread->kernel_stack_size;
|
||||||
stack -= sizeof(struct interrupt_context);
|
stack -= sizeof(struct interrupt_context);
|
||||||
struct interrupt_context* fakectx = (struct interrupt_context*) stack;
|
struct interrupt_context* fakectx = (struct interrupt_context*) stack;
|
||||||
memcpy(fakectx, intctx, sizeof(struct interrupt_context));
|
memcpy(fakectx, intctx, sizeof(struct interrupt_context));
|
||||||
|
|
|
@ -144,8 +144,8 @@ int sys_sigaction(int signum,
|
||||||
memcpy(kact, &newact, sizeof(struct sigaction));
|
memcpy(kact, &newact, sizeof(struct sigaction));
|
||||||
|
|
||||||
// Signals may become discarded because of the new handler.
|
// Signals may become discarded because of the new handler.
|
||||||
ScopedLock threads_lock(&process->threadlock);
|
ScopedLock threads_lock(&process->thread_lock);
|
||||||
for ( Thread* t = process->firstthread; t; t = t->nextsibling )
|
for ( Thread* t = process->first_thread; t; t = t->next_sibling )
|
||||||
UpdatePendingSignals(t);
|
UpdatePendingSignals(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,9 +315,9 @@ int sys_kill(pid_t pid, int signum)
|
||||||
|
|
||||||
bool Process::DeliverGroupSignal(int signum) // process_family_lock held
|
bool Process::DeliverGroupSignal(int signum) // process_family_lock held
|
||||||
{
|
{
|
||||||
if ( !groupfirst )
|
if ( !group_first )
|
||||||
return errno = ESRCH, false;
|
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;
|
int saved_errno = errno;
|
||||||
if ( !iter->DeliverSignal(signum) && errno != ESIGPENDING )
|
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
|
bool Process::DeliverSessionSignal(int signum) // process_family_lock held
|
||||||
{
|
{
|
||||||
if ( !sessionfirst )
|
if ( !session_first )
|
||||||
return errno = ESRCH, false;
|
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;
|
int saved_errno = errno;
|
||||||
if ( !iter->DeliverSignal(signum) && errno != ESIGPENDING )
|
if ( !iter->DeliverSignal(signum) && errno != ESIGPENDING )
|
||||||
|
@ -347,16 +347,16 @@ bool Process::DeliverSessionSignal(int signum) // process_family_lock held
|
||||||
|
|
||||||
bool Process::DeliverSignal(int signum)
|
bool Process::DeliverSignal(int signum)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&threadlock);
|
ScopedLock lock(&thread_lock);
|
||||||
|
|
||||||
if ( !firstthread )
|
if ( !first_thread )
|
||||||
return errno = EINIT, false;
|
return errno = EINIT, false;
|
||||||
|
|
||||||
// Broadcast particular signals to all the threads in the process.
|
// Broadcast particular signals to all the threads in the process.
|
||||||
if ( signum == SIGCONT || signum == SIGSTOP || signum == SIGKILL )
|
if ( signum == SIGCONT || signum == SIGSTOP || signum == SIGKILL )
|
||||||
{
|
{
|
||||||
int saved_errno = errno;
|
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 )
|
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.
|
// TODO: This isn't how signals should be routed to a particular thread.
|
||||||
if ( CurrentThread()->process == this )
|
if ( CurrentThread()->process == this )
|
||||||
return CurrentThread()->DeliverSignal(signum);
|
return CurrentThread()->DeliverSignal(signum);
|
||||||
return firstthread->DeliverSignal(signum);
|
return first_thread->DeliverSignal(signum);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_raise(int signum)
|
int sys_raise(int signum)
|
||||||
|
|
|
@ -59,18 +59,18 @@ Thread::Thread()
|
||||||
yield_to_tid = 0;
|
yield_to_tid = 0;
|
||||||
id = 0; // TODO: Make a thread id.
|
id = 0; // TODO: Make a thread id.
|
||||||
process = NULL;
|
process = NULL;
|
||||||
prevsibling = NULL;
|
prev_sibling = NULL;
|
||||||
nextsibling = NULL;
|
next_sibling = NULL;
|
||||||
scheduler_list_prev = NULL;
|
scheduler_list_prev = NULL;
|
||||||
scheduler_list_next = NULL;
|
scheduler_list_next = NULL;
|
||||||
state = NONE;
|
state = NONE;
|
||||||
memset(®isters, 0, sizeof(registers));
|
memset(®isters, 0, sizeof(registers));
|
||||||
kernelstackpos = 0;
|
kernel_stack_pos = 0;
|
||||||
kernelstacksize = 0;
|
kernel_stack_size = 0;
|
||||||
signal_count = 0;
|
signal_count = 0;
|
||||||
signal_single_frame = 0;
|
signal_single_frame = 0;
|
||||||
signal_canary = 0;
|
signal_canary = 0;
|
||||||
kernelstackmalloced = false;
|
kernel_stack_malloced = false;
|
||||||
pledged_destruction = false;
|
pledged_destruction = false;
|
||||||
force_no_signals = false;
|
force_no_signals = false;
|
||||||
signal_single = false;
|
signal_single = false;
|
||||||
|
@ -99,8 +99,8 @@ Thread::~Thread()
|
||||||
if ( process )
|
if ( process )
|
||||||
process->OnThreadDestruction(this);
|
process->OnThreadDestruction(this);
|
||||||
assert(CurrentThread() != this);
|
assert(CurrentThread() != this);
|
||||||
if ( kernelstackmalloced )
|
if ( kernel_stack_malloced )
|
||||||
delete[] (uint8_t*) kernelstackpos;
|
delete[] (uint8_t*) kernel_stack_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* CreateKernelThread(Process* process,
|
Thread* CreateKernelThread(Process* process,
|
||||||
|
@ -116,7 +116,7 @@ Thread* CreateKernelThread(Process* process,
|
||||||
return errno = EINVAL, (Thread*) NULL;
|
return errno = EINVAL, (Thread*) NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
kthread_mutex_lock(&process->threadlock);
|
kthread_mutex_lock(&process->thread_lock);
|
||||||
|
|
||||||
// Note: Only allow the process itself to make threads, except the initial
|
// Note: Only allow the process itself to make threads, except the initial
|
||||||
// thread. This requirement is because kthread_exit() needs to know when
|
// 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
|
// 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
|
// termination steps without any interference. It's always allowed to create
|
||||||
// threads in the kernel process as it never exits.
|
// threads in the kernel process as it never exits.
|
||||||
assert(!process->firstthread ||
|
assert(!process->first_thread ||
|
||||||
process == CurrentProcess() ||
|
process == CurrentProcess() ||
|
||||||
process == Scheduler::GetKernelProcess());
|
process == Scheduler::GetKernelProcess());
|
||||||
|
|
||||||
|
@ -137,14 +137,14 @@ Thread* CreateKernelThread(Process* process,
|
||||||
|
|
||||||
// Create the family tree.
|
// Create the family tree.
|
||||||
thread->process = process;
|
thread->process = process;
|
||||||
Thread* firsty = process->firstthread;
|
Thread* firsty = process->first_thread;
|
||||||
if ( firsty )
|
if ( firsty )
|
||||||
firsty->prevsibling = thread;
|
firsty->prev_sibling = thread;
|
||||||
thread->nextsibling = firsty;
|
thread->next_sibling = firsty;
|
||||||
process->firstthread = thread;
|
process->first_thread = thread;
|
||||||
process->threads_not_exiting_count++;
|
process->threads_not_exiting_count++;
|
||||||
|
|
||||||
kthread_mutex_unlock(&process->threadlock);
|
kthread_mutex_unlock(&process->thread_lock);
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
@ -260,9 +260,9 @@ Thread* CreateKernelThread(Process* process, void (*entry)(void*), void* user,
|
||||||
Thread* thread = CreateKernelThread(process, ®s, name);
|
Thread* thread = CreateKernelThread(process, ®s, name);
|
||||||
if ( !thread ) { delete[] stack; return NULL; }
|
if ( !thread ) { delete[] stack; return NULL; }
|
||||||
|
|
||||||
thread->kernelstackpos = (uintptr_t) stack;
|
thread->kernel_stack_pos = (uintptr_t) stack;
|
||||||
thread->kernelstacksize = stacksize;
|
thread->kernel_stack_size = stacksize;
|
||||||
thread->kernelstackmalloced = true;
|
thread->kernel_stack_malloced = true;
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
@ -335,11 +335,11 @@ int sys_exit_thread(int requested_exit_code,
|
||||||
|
|
||||||
extended.unmap_size = Page::AlignUp(extended.unmap_size);
|
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;
|
bool is_others = false;
|
||||||
for ( Thread* iter = thread->process->firstthread;
|
for ( Thread* iter = thread->process->first_thread;
|
||||||
!is_others && iter;
|
!is_others && iter;
|
||||||
iter = iter->nextsibling )
|
iter = iter->next_sibling )
|
||||||
{
|
{
|
||||||
if ( iter == thread )
|
if ( iter == thread )
|
||||||
continue;
|
continue;
|
||||||
|
@ -355,7 +355,7 @@ int sys_exit_thread(int requested_exit_code,
|
||||||
process->threads_exiting = true;
|
process->threads_exiting = true;
|
||||||
else if ( process->threads_exiting )
|
else if ( process->threads_exiting )
|
||||||
are_threads_exiting = true;
|
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.
|
// Self-destruct if another thread began exiting the process.
|
||||||
if ( are_threads_exiting )
|
if ( are_threads_exiting )
|
||||||
|
|
|
@ -295,7 +295,7 @@ int TTY::tcsetpgrp(ioctx_t* /*ctx*/, pid_t pgid)
|
||||||
Process* process = CurrentProcess()->GetPTable()->Get(pgid);
|
Process* process = CurrentProcess()->GetPTable()->Get(pgid);
|
||||||
if ( !process )
|
if ( !process )
|
||||||
return errno = ESRCH, -1;
|
return errno = ESRCH, -1;
|
||||||
if ( !process->groupfirst )
|
if ( !process->group_first )
|
||||||
return errno = EINVAL, -1;
|
return errno = EINVAL, -1;
|
||||||
foreground_pgid = pgid;
|
foreground_pgid = pgid;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -864,7 +864,7 @@ int TTY::ioctl(ioctx_t* ctx, int cmd, uintptr_t arg)
|
||||||
return errno = EPERM, -1;
|
return errno = EPERM, -1;
|
||||||
ScopedLock family_lock(&process_family_lock);
|
ScopedLock family_lock(&process_family_lock);
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
if ( !force && !process->sessionfirst )
|
if ( !force && !process->session_first )
|
||||||
return errno = EPERM, -1;
|
return errno = EPERM, -1;
|
||||||
Process* session = process->session;
|
Process* session = process->session;
|
||||||
// TODO: Don't do this if the sesion already has a tty.
|
// TODO: Don't do this if the sesion already has a tty.
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*
|
*
|
||||||
* framebuffer.c
|
* framebuffer.c
|
||||||
* Framebuffer functions.
|
* Framebuffer utilities.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "pixel.h"
|
#include "pixel.h"
|
||||||
|
#include "vgafont.h"
|
||||||
|
|
||||||
struct framebuffer framebuffer_crop(struct framebuffer fb,
|
struct framebuffer framebuffer_crop(struct framebuffer fb,
|
||||||
size_t left,
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*
|
*
|
||||||
* framebuffer.h
|
* framebuffer.h
|
||||||
* Framebuffer functions.
|
* Framebuffer utilities.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FRAMEBUFFER_H
|
#ifndef FRAMEBUFFER_H
|
||||||
|
@ -59,5 +59,22 @@ void framebuffer_copy_to_framebuffer(const struct framebuffer dst,
|
||||||
const struct framebuffer src);
|
const struct framebuffer src);
|
||||||
void framebuffer_copy_to_framebuffer_blend(const struct framebuffer dst,
|
void framebuffer_copy_to_framebuffer_blend(const struct framebuffer dst,
|
||||||
const struct framebuffer src);
|
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
|
#endif
|
||||||
|
|
|
@ -63,6 +63,7 @@ enum stage
|
||||||
STAGE_USERNAME,
|
STAGE_USERNAME,
|
||||||
STAGE_PASSWORD,
|
STAGE_PASSWORD,
|
||||||
STAGE_CHECKING,
|
STAGE_CHECKING,
|
||||||
|
STAGE_EXITING,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct textbox
|
struct textbox
|
||||||
|
@ -111,6 +112,7 @@ struct glogin
|
||||||
enum stage stage;
|
enum stage stage;
|
||||||
bool animating;
|
bool animating;
|
||||||
const char* warning;
|
const char* warning;
|
||||||
|
const char* announcement;
|
||||||
bool pointer_working;
|
bool pointer_working;
|
||||||
struct termios old_tio;
|
struct termios old_tio;
|
||||||
bool has_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)
|
static void render_login(struct framebuffer fb)
|
||||||
{
|
{
|
||||||
render_background(fb);
|
render_background(fb);
|
||||||
|
@ -509,6 +538,7 @@ static void render_login(struct framebuffer fb)
|
||||||
case STAGE_USERNAME: render_form(fb); break;
|
case STAGE_USERNAME: render_form(fb); break;
|
||||||
case STAGE_PASSWORD: render_form(fb); break;
|
case STAGE_PASSWORD: render_form(fb); break;
|
||||||
case STAGE_CHECKING: render_progress(fb); break;
|
case STAGE_CHECKING: render_progress(fb); break;
|
||||||
|
case STAGE_EXITING: render_exit(fb); break;
|
||||||
}
|
}
|
||||||
if ( state.pointer_working )
|
if ( state.pointer_working )
|
||||||
render_pointer(fb);
|
render_pointer(fb);
|
||||||
|
@ -669,6 +699,52 @@ static bool render(struct glogin* state)
|
||||||
return true;
|
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)
|
static void think(struct glogin* state)
|
||||||
{
|
{
|
||||||
if ( state->stage == STAGE_CHECKING )
|
if ( state->stage == STAGE_CHECKING )
|
||||||
|
@ -679,6 +755,7 @@ static void think(struct glogin* state)
|
||||||
sched_yield();
|
sched_yield();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
forward_sigterm_to = 0;
|
||||||
if ( result )
|
if ( result )
|
||||||
{
|
{
|
||||||
if ( !login(username, session) )
|
if ( !login(username, session) )
|
||||||
|
@ -696,6 +773,22 @@ static void think(struct glogin* state)
|
||||||
state->warning = strerror(errno);
|
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)
|
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";
|
state->warning = "Invalid username";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
handle_special(action);
|
handle_special_graphical(state, action);
|
||||||
state->stage = STAGE_PASSWORD;
|
state->stage = STAGE_PASSWORD;
|
||||||
textbox_reset(&textbox_password);
|
textbox_reset(&textbox_password);
|
||||||
break;
|
break;
|
||||||
|
@ -729,8 +822,10 @@ static void keyboard_event(struct glogin* state, uint32_t codepoint)
|
||||||
state->stage = STAGE_USERNAME;
|
state->stage = STAGE_USERNAME;
|
||||||
state->warning = strerror(errno);
|
state->warning = strerror(errno);
|
||||||
}
|
}
|
||||||
|
forward_sigterm_to = state->chk.pid;
|
||||||
break;
|
break;
|
||||||
case STAGE_CHECKING:
|
case STAGE_CHECKING:
|
||||||
|
case STAGE_EXITING:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -741,6 +836,7 @@ static void keyboard_event(struct glogin* state, uint32_t codepoint)
|
||||||
case STAGE_USERNAME: textbox = &textbox_username; break;
|
case STAGE_USERNAME: textbox = &textbox_username; break;
|
||||||
case STAGE_PASSWORD: textbox = &textbox_password; break;
|
case STAGE_PASSWORD: textbox = &textbox_password; break;
|
||||||
case STAGE_CHECKING: break;
|
case STAGE_CHECKING: break;
|
||||||
|
case STAGE_EXITING: break;
|
||||||
}
|
}
|
||||||
if ( textbox && codepoint < 128 )
|
if ( textbox && codepoint < 128 )
|
||||||
{
|
{
|
||||||
|
@ -871,6 +967,12 @@ bool glogin_init(struct glogin* state)
|
||||||
struct timespec duration = timespec_make(0, 150*1000*1000);
|
struct timespec duration = timespec_make(0, 150*1000*1000);
|
||||||
state->fade_from_end = timespec_add(state->fade_from_begin, duration);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,9 +1002,14 @@ int glogin_main(struct glogin* state)
|
||||||
nfds_t nfds = 2;
|
nfds_t nfds = 2;
|
||||||
struct timespec wake_now_ts = timespec_make(0, 0);
|
struct timespec wake_now_ts = timespec_make(0, 0);
|
||||||
struct timespec* wake = state->animating ? &wake_now_ts : NULL;
|
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 ( num_events < 0 )
|
||||||
{
|
{
|
||||||
|
if ( errno == EINTR )
|
||||||
|
continue;
|
||||||
warn("poll");
|
warn("poll");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* Copyright (c) 2023 dzwdz.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
@ -46,12 +46,21 @@
|
||||||
|
|
||||||
#include "login.h"
|
#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 )
|
if ( signum == SIGINT )
|
||||||
dprintf(1, "^C");
|
dprintf(1, "^C");
|
||||||
if ( signum == SIGQUIT )
|
if ( signum == SIGQUIT )
|
||||||
dprintf(1, "^\\");
|
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)
|
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, SIGINT);
|
||||||
sigdelset(&chk->oldset, SIGQUIT);
|
sigdelset(&chk->oldset, SIGQUIT);
|
||||||
|
sigdelset(&chk->oldset, SIGTERM);
|
||||||
signal(SIGINT, SIG_DFL);
|
signal(SIGINT, SIG_DFL);
|
||||||
signal(SIGQUIT, SIG_DFL);
|
signal(SIGQUIT, SIG_DFL);
|
||||||
|
signal(SIGTERM, SIG_DFL);
|
||||||
unsigned int termmode = TERMMODE_UNICODE | TERMMODE_SIGNAL |
|
unsigned int termmode = TERMMODE_UNICODE | TERMMODE_SIGNAL |
|
||||||
TERMMODE_UTF8 | TERMMODE_LINEBUFFER |
|
TERMMODE_UTF8 | TERMMODE_LINEBUFFER |
|
||||||
TERMMODE_ECHO;
|
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);
|
fcntl(chk->pipe, F_SETFL, fcntl(chk->pipe, F_GETFL) | O_NONBLOCK);
|
||||||
chk->pipe_nonblock = true;
|
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) )
|
while ( chk->errnum_done < sizeof(chk->errnum_bytes) )
|
||||||
{
|
{
|
||||||
ssize_t amount = read(chk->pipe, chk->errnum_bytes + chk->errnum_done,
|
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;
|
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;
|
int code;
|
||||||
pid_t wait_ret = waitpid(chk->pid, &code, try ? WNOHANG : 0);
|
pid_t wait_ret = waitpid(chk->pid, &code, try ? WNOHANG : 0);
|
||||||
if ( try && wait_ret == 0 )
|
if ( try && wait_ret == 0 )
|
||||||
|
@ -232,9 +261,11 @@ bool login(const char* username, const char* session)
|
||||||
{
|
{
|
||||||
sigdelset(&oldset, SIGINT);
|
sigdelset(&oldset, SIGINT);
|
||||||
sigdelset(&oldset, SIGQUIT);
|
sigdelset(&oldset, SIGQUIT);
|
||||||
|
sigdelset(&oldset, SIGTERM);
|
||||||
sigdelset(&oldset, SIGTSTP);
|
sigdelset(&oldset, SIGTSTP);
|
||||||
signal(SIGINT, SIG_DFL);
|
signal(SIGINT, SIG_DFL);
|
||||||
signal(SIGQUIT, SIG_DFL);
|
signal(SIGQUIT, SIG_DFL);
|
||||||
|
signal(SIGTERM, SIG_DFL);
|
||||||
(void) (
|
(void) (
|
||||||
setpgid(0, 0) < 0 ||
|
setpgid(0, 0) < 0 ||
|
||||||
close(pipe_fds[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 ||
|
open("/dev/tty", O_WRONLY) != 2 ||
|
||||||
setcloexecfrom(3) < 0 ||
|
setcloexecfrom(3) < 0 ||
|
||||||
tcsetpgrp(0, getpgid(0)) ||
|
tcsetpgrp(0, getpgid(0)) ||
|
||||||
|
// TODO: Do this immediately? At least unblock SIGTERM.
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL) < 0 ||
|
sigprocmask(SIG_SETMASK, &oldset, NULL) < 0 ||
|
||||||
settermmode(0, TERMMODE_NORMAL) < 0 ||
|
settermmode(0, TERMMODE_NORMAL) < 0 ||
|
||||||
(session ?
|
(session ?
|
||||||
|
@ -269,13 +301,34 @@ bool login(const char* username, const char* session)
|
||||||
}
|
}
|
||||||
free(login_shell);
|
free(login_shell);
|
||||||
close(pipe_fds[1]);
|
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;
|
int errnum;
|
||||||
if ( readall(pipe_fds[0], &errnum, sizeof(errnum)) < (ssize_t) sizeof(errnum) )
|
if ( readall(pipe_fds[0], &errnum, sizeof(errnum)) < (ssize_t) sizeof(errnum) )
|
||||||
errnum = 0;
|
errnum = 0;
|
||||||
close(pipe_fds[0]);
|
close(pipe_fds[0]);
|
||||||
int child_status;
|
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;
|
errnum = errno;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigprocmask(SIG_BLOCK, &sigterm, NULL);
|
||||||
|
forward_sigterm_to = 0;
|
||||||
|
sigaction(SIGTERM, &old_sa, NULL);
|
||||||
|
|
||||||
tcsetattr(0, TCSAFLUSH, &tio);
|
tcsetattr(0, TCSAFLUSH, &tio);
|
||||||
tcsetpgrp(0, getpgid(0));
|
tcsetpgrp(0, getpgid(0));
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
|
@ -334,7 +387,7 @@ bool parse_username(const char* input,
|
||||||
*session = NULL;
|
*session = NULL;
|
||||||
*action = SPECIAL_ACTION_NONE;
|
*action = SPECIAL_ACTION_NONE;
|
||||||
if ( !strcmp(input, "exit") )
|
if ( !strcmp(input, "exit") )
|
||||||
return *action = SPECIAL_ACTION_POWEROFF, true;
|
return *action = SPECIAL_ACTION_EXIT, true;
|
||||||
else if ( !strcmp(input, "poweroff") )
|
else if ( !strcmp(input, "poweroff") )
|
||||||
return *action = SPECIAL_ACTION_POWEROFF, true;
|
return *action = SPECIAL_ACTION_POWEROFF, true;
|
||||||
else if ( !strcmp(input, "reboot") )
|
else if ( !strcmp(input, "reboot") )
|
||||||
|
@ -376,6 +429,7 @@ void handle_special(enum special_action action)
|
||||||
switch ( action )
|
switch ( action )
|
||||||
{
|
{
|
||||||
case SPECIAL_ACTION_NONE: return;
|
case SPECIAL_ACTION_NONE: return;
|
||||||
|
case SPECIAL_ACTION_EXIT: exit(0);
|
||||||
case SPECIAL_ACTION_POWEROFF: exit(0);
|
case SPECIAL_ACTION_POWEROFF: exit(0);
|
||||||
case SPECIAL_ACTION_REBOOT: exit(1);
|
case SPECIAL_ACTION_REBOOT: exit(1);
|
||||||
case SPECIAL_ACTION_HALT: exit(2);
|
case SPECIAL_ACTION_HALT: exit(2);
|
||||||
|
@ -394,7 +448,7 @@ int textual(void)
|
||||||
char* username = NULL;
|
char* username = NULL;
|
||||||
char* session = NULL;
|
char* session = NULL;
|
||||||
|
|
||||||
while ( true )
|
while ( !got_sigterm )
|
||||||
{
|
{
|
||||||
char hostname[HOST_NAME_MAX + 1];
|
char hostname[HOST_NAME_MAX + 1];
|
||||||
hostname[0] = '\0';
|
hostname[0] = '\0';
|
||||||
|
@ -460,6 +514,9 @@ int textual(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( got_sigterm )
|
||||||
|
break;
|
||||||
|
|
||||||
if ( !login(username, session) )
|
if ( !login(username, session) )
|
||||||
{
|
{
|
||||||
warn("logging in as %s", username);
|
warn("logging in as %s", username);
|
||||||
|
|
|
@ -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.
|
* Copyright (c) 2023 dzwdz.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
@ -39,12 +39,14 @@ struct check
|
||||||
enum special_action
|
enum special_action
|
||||||
{
|
{
|
||||||
SPECIAL_ACTION_NONE,
|
SPECIAL_ACTION_NONE,
|
||||||
|
SPECIAL_ACTION_EXIT,
|
||||||
SPECIAL_ACTION_POWEROFF,
|
SPECIAL_ACTION_POWEROFF,
|
||||||
SPECIAL_ACTION_REBOOT,
|
SPECIAL_ACTION_REBOOT,
|
||||||
SPECIAL_ACTION_HALT,
|
SPECIAL_ACTION_HALT,
|
||||||
SPECIAL_ACTION_REINIT,
|
SPECIAL_ACTION_REINIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void on_interrupt_signal(int signum);
|
||||||
bool login(const char* username, const char* session);
|
bool login(const char* username, const char* session);
|
||||||
bool check_real(const char* username, const char* password);
|
bool check_real(const char* username, const char* password);
|
||||||
bool check_begin(struct check* chk,
|
bool check_begin(struct check* chk,
|
||||||
|
@ -62,4 +64,7 @@ bool parse_username(const char* input,
|
||||||
enum special_action* action);
|
enum special_action* action);
|
||||||
void handle_special(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
|
#endif
|
||||||
|
|
10
sh/sh.c
10
sh/sh.c
|
@ -1183,6 +1183,8 @@ struct execute_result execute(char** tokens,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal(SIGHUP, SIG_DFL);
|
||||||
|
|
||||||
setpgid(0, pgid != -1 ? pgid : 0);
|
setpgid(0, pgid != -1 ? pgid : 0);
|
||||||
if ( interactive && pgid == -1 )
|
if ( interactive && pgid == -1 )
|
||||||
{
|
{
|
||||||
|
@ -2042,7 +2044,7 @@ static int run(FILE* fp,
|
||||||
read_command_non_interactive(&sh_read_command, fp);
|
read_command_non_interactive(&sh_read_command, fp);
|
||||||
|
|
||||||
if ( sh_read_command.abort_condition )
|
if ( sh_read_command.abort_condition )
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
if ( sh_read_command.eof_condition )
|
if ( sh_read_command.eof_condition )
|
||||||
{
|
{
|
||||||
|
@ -2137,6 +2139,9 @@ static int top(FILE* fp,
|
||||||
if ( *script_exited || (status != 0 && exit_on_error) )
|
if ( *script_exited || (status != 0 && exit_on_error) )
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
// Receive read EOF instead so we save the shell history.
|
||||||
|
signal(SIGHUP, SIG_IGN);
|
||||||
|
|
||||||
edit_line_history_load(&edit_state, getenv("HISTFILE"));
|
edit_line_history_load(&edit_state, getenv("HISTFILE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2144,7 +2149,10 @@ static int top(FILE* fp,
|
||||||
status);
|
status);
|
||||||
|
|
||||||
if ( interactive )
|
if ( interactive )
|
||||||
|
{
|
||||||
edit_line_history_save(&edit_state, getenv("HISTFILE"));
|
edit_line_history_save(&edit_state, getenv("HISTFILE"));
|
||||||
|
signal(SIGHUP, SIG_DFL);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue