Compare commits
19 Commits
2c9bdb7a9a
...
dc7894d61e
Author | SHA1 | Date |
---|---|---|
Jonas 'Sortie' Termansen | dc7894d61e | |
Jonas 'Sortie' Termansen | 017e6fe13e | |
Jonas 'Sortie' Termansen | 9c5ea68951 | |
Jonas 'Sortie' Termansen | c488b8a8fc | |
Jonas 'Sortie' Termansen | 51e483b537 | |
Jonas 'Sortie' Termansen | ca9ec73726 | |
Jonas 'Sortie' Termansen | 818f4c4ecd | |
Jonas 'Sortie' Termansen | 4e72a157fa | |
Jonas 'Sortie' Termansen | f551b4afa8 | |
Jonas 'Sortie' Termansen | b676a5f2da | |
Jonas 'Sortie' Termansen | 6f70708ff5 | |
Jonas 'Sortie' Termansen | 4187705c9f | |
Jonas 'Sortie' Termansen | e737851ae6 | |
Jonas 'Sortie' Termansen | 0e31e0c578 | |
Jonas 'Sortie' Termansen | 251e770e07 | |
Jonas 'Sortie' Termansen | 3036bf3f09 | |
Jonas 'Sortie' Termansen | 0e5cbea003 | |
Jonas 'Sortie' Termansen | 235f7fbb11 | |
Jonas 'Sortie' Termansen | 55ba7b7507 |
|
@ -160,6 +160,7 @@ void display_unmark_active_window(struct display* display,
|
|||
window->focus = false;
|
||||
display->active_window = NULL;
|
||||
window_render_frame(window);
|
||||
window_unsend_keys(window);
|
||||
}
|
||||
|
||||
void display_mark_active_window(struct display* display, struct window* window)
|
||||
|
@ -466,6 +467,11 @@ void display_keyboard_event(struct display* display, uint32_t codepoint)
|
|||
int kbkey = KBKEY_DECODE(codepoint);
|
||||
int abskbkey = kbkey < 0 ? -kbkey : kbkey;
|
||||
|
||||
if ( !kbkey && display->codepoint_discard )
|
||||
return;
|
||||
else if ( kbkey < 0 )
|
||||
display->codepoint_discard = false;
|
||||
|
||||
if ( kbkey && (!window || !window->grab_input) )
|
||||
{
|
||||
switch ( abskbkey )
|
||||
|
@ -484,6 +490,7 @@ void display_keyboard_event(struct display* display, uint32_t codepoint)
|
|||
execlp("terminal", "terminal", (char*) NULL);
|
||||
_exit(127);
|
||||
}
|
||||
display->codepoint_discard = true;
|
||||
return;
|
||||
}
|
||||
else if ( display->key_lctrl && display->key_lalt && kbkey == -KBKEY_T )
|
||||
|
@ -496,18 +503,21 @@ void display_keyboard_event(struct display* display, uint32_t codepoint)
|
|||
if ( (display->key_lalt && kbkey == KBKEY_F4) /* ||
|
||||
(display->key_lctrl && kbkey == KBKEY_Q)*/ )
|
||||
{
|
||||
display->codepoint_discard = true;
|
||||
window_quit(window);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( display->key_lalt && kbkey == KBKEY_F10 )
|
||||
{
|
||||
display->codepoint_discard = true;
|
||||
window_toggle_maximized(display->active_window);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( display->key_lalt && kbkey == KBKEY_TAB )
|
||||
{
|
||||
display->codepoint_discard = true;
|
||||
if ( !display->tab_candidate )
|
||||
display->tab_candidate = display->active_window;
|
||||
struct window* old_candidate = display->tab_candidate;
|
||||
|
@ -531,21 +541,25 @@ void display_keyboard_event(struct display* display, uint32_t codepoint)
|
|||
struct window* window = display->active_window;
|
||||
if ( kbkey == KBKEY_LEFT )
|
||||
{
|
||||
display->codepoint_discard = true;
|
||||
window_tile_leftward(window);
|
||||
return;
|
||||
}
|
||||
if ( kbkey == KBKEY_RIGHT )
|
||||
{
|
||||
display->codepoint_discard = true;
|
||||
window_tile_rightward(window);
|
||||
return;
|
||||
}
|
||||
if ( kbkey == KBKEY_UP )
|
||||
{
|
||||
display->codepoint_discard = true;
|
||||
window_tile_up(window);
|
||||
return;
|
||||
}
|
||||
if ( kbkey == KBKEY_DOWN )
|
||||
{
|
||||
display->codepoint_discard = true;
|
||||
window_tile_down(window);
|
||||
return;
|
||||
}
|
||||
|
@ -580,18 +594,7 @@ void display_keyboard_event(struct display* display, uint32_t codepoint)
|
|||
if ( !window )
|
||||
return;
|
||||
|
||||
struct event_keyboard event;
|
||||
event.window_id = display->active_window->window_id;
|
||||
event.codepoint = codepoint;
|
||||
|
||||
struct display_packet_header header;
|
||||
header.id = EVENT_KEYBOARD;
|
||||
header.size = sizeof(event);
|
||||
|
||||
assert(window->connection);
|
||||
|
||||
connection_schedule_transmit(window->connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(window->connection, &event, sizeof(event));
|
||||
window_send_key(display->active_window, codepoint);
|
||||
}
|
||||
|
||||
void display_mouse_event(struct display* display, uint8_t byte)
|
||||
|
|
|
@ -66,6 +66,7 @@ struct display
|
|||
bool key_lalt;
|
||||
bool key_lsuper;
|
||||
bool key_rsuper;
|
||||
bool codepoint_discard;
|
||||
bool redraw;
|
||||
int pointer_x;
|
||||
int pointer_y;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2015, 2016, 2017, 2022, 2023 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2014-2017, 2022-2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -17,6 +17,8 @@
|
|||
* Window abstraction.
|
||||
*/
|
||||
|
||||
#include <sys/keycodes.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -573,3 +575,61 @@ void window_notify_client_resize(struct window* window)
|
|||
connection_schedule_transmit(window->connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(window->connection, &event, sizeof(event));
|
||||
}
|
||||
|
||||
void window_send_key(struct window* window, uint32_t codepoint)
|
||||
{
|
||||
int kbkey = KBKEY_DECODE(codepoint);
|
||||
unsigned int abskbkey = kbkey < 0 ? -kbkey : kbkey;
|
||||
if ( 0 < abskbkey && abskbkey < 512 )
|
||||
{
|
||||
size_t index = abskbkey / (8 * sizeof(size_t));
|
||||
size_t bit = abskbkey % (8 * sizeof(size_t));
|
||||
size_t mask = 1ULL << bit;
|
||||
if ( kbkey < 0 )
|
||||
window->key_bitmap[index] &= ~mask;
|
||||
else
|
||||
window->key_bitmap[index] |= mask;
|
||||
}
|
||||
|
||||
struct event_keyboard event;
|
||||
event.window_id = window->window_id;
|
||||
event.codepoint = codepoint;
|
||||
|
||||
struct display_packet_header header;
|
||||
header.id = EVENT_KEYBOARD;
|
||||
header.size = sizeof(event);
|
||||
|
||||
assert(window->connection);
|
||||
|
||||
connection_schedule_transmit(window->connection, &header, sizeof(header));
|
||||
connection_schedule_transmit(window->connection, &event, sizeof(event));
|
||||
}
|
||||
|
||||
void window_unsend_keys(struct window* window)
|
||||
{
|
||||
struct event_keyboard event;
|
||||
event.window_id = window->window_id;
|
||||
event.codepoint = 0;
|
||||
|
||||
struct display_packet_header header;
|
||||
header.id = EVENT_KEYBOARD;
|
||||
header.size = sizeof(event);
|
||||
|
||||
assert(window->connection);
|
||||
|
||||
for ( int kbkey = 1; kbkey < 512; kbkey++ )
|
||||
{
|
||||
size_t index = kbkey / (8 * sizeof(size_t));
|
||||
size_t bit = kbkey % (8 * sizeof(size_t));
|
||||
size_t mask = 1ULL << bit;
|
||||
if ( window->key_bitmap[index] & mask )
|
||||
{
|
||||
event.codepoint = KBKEY_ENCODE(-kbkey);
|
||||
connection_schedule_transmit(window->connection, &header,
|
||||
sizeof(header));
|
||||
connection_schedule_transmit(window->connection, &event,
|
||||
sizeof(event));
|
||||
}
|
||||
}
|
||||
memset(window->key_bitmap, 0, sizeof(window->key_bitmap));
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ struct window
|
|||
bool show;
|
||||
bool focus;
|
||||
bool grab_input;
|
||||
size_t key_bitmap[512 / (8 * sizeof(size_t))];
|
||||
};
|
||||
|
||||
struct framebuffer window_client_buffer(struct window* window);
|
||||
|
@ -115,5 +116,7 @@ void window_tile_bottom(struct window* window);
|
|||
void window_tile_bottom_left(struct window* window);
|
||||
void window_tile_bottom_right(struct window* window);
|
||||
void window_notify_client_resize(struct window* window);
|
||||
void window_send_key(struct window* window, uint32_t codepoint);
|
||||
void window_unsend_keys(struct window* window);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2014, 2016 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2013, 2014, 2016, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -257,8 +258,8 @@ void editor_input_begin(struct editor_input* editor_input)
|
|||
}
|
||||
}
|
||||
|
||||
void editor_input_process(struct editor_input* editor_input,
|
||||
struct editor* editor)
|
||||
void editor_input_process_byte(struct editor_input* editor_input,
|
||||
struct editor* editor)
|
||||
{
|
||||
unsigned char uc;
|
||||
ssize_t amount_read = read(0, &uc, sizeof(uc));
|
||||
|
@ -352,6 +353,14 @@ void editor_input_process(struct editor_input* editor_input,
|
|||
}
|
||||
}
|
||||
|
||||
void editor_input_process(struct editor_input* editor_input,
|
||||
struct editor* editor)
|
||||
{
|
||||
struct pollfd pfd = { .fd = 0, .events = POLLIN };
|
||||
do editor_input_process_byte(editor_input, editor);
|
||||
while ( poll(&pfd, 1, 0) == 1 );
|
||||
}
|
||||
|
||||
void editor_input_end(struct editor_input* editor_input)
|
||||
{
|
||||
if ( getenv("TERM") && strcmp(getenv("TERM"), "sortix") != 0 )
|
||||
|
|
|
@ -270,16 +270,16 @@ int main(int argc, char* argv[])
|
|||
|
||||
if ( write && sb.s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPPORTED )
|
||||
{
|
||||
warn("warning: %s: Uses unsupported and incompatible features, "
|
||||
"falling back to read-only access\n", device_path);
|
||||
warnx("warning: %s: Uses unsupported and incompatible features, "
|
||||
"falling back to read-only access", device_path);
|
||||
// TODO: Modify the file descriptor such that writing fails!
|
||||
write = false;
|
||||
}
|
||||
|
||||
// Check whether any features are in use that we can safely disregard.
|
||||
if ( sb.s_feature_compat & ~EXT2_FEATURE_COMPAT_SUPPORTED )
|
||||
warn("%s: Filesystem uses unsupported but compatible features\n",
|
||||
device_path);
|
||||
warnx("%s: Filesystem uses unsupported but compatible features",
|
||||
device_path);
|
||||
|
||||
// Check the block size is sane. 64 KiB may have issues, 32 KiB then.
|
||||
if ( sb.s_log_block_size > (15-10) /* 32 KiB blocks */ )
|
||||
|
@ -287,7 +287,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
// Check whether the filesystem was unmounted cleanly.
|
||||
if ( sb.s_state != EXT2_VALID_FS )
|
||||
warn("warning: %s: Filesystem wasn't unmounted cleanly\n", device_path);
|
||||
warnx("warning: %s: Filesystem wasn't unmounted cleanly", device_path);
|
||||
|
||||
uint32_t block_size = 1024U << sb.s_log_block_size;
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
init
|
||||
*.o
|
||||
service
|
||||
|
|
|
@ -8,26 +8,27 @@ CFLAGS?=$(OPTLEVEL)
|
|||
|
||||
CFLAGS:=$(CFLAGS) -Wall -Wextra
|
||||
|
||||
BINARY=init
|
||||
BINARIES=\
|
||||
init \
|
||||
service \
|
||||
|
||||
OBJS=\
|
||||
init.o \
|
||||
MANPAGES8=\
|
||||
init.8 \
|
||||
|
||||
all: $(BINARY)
|
||||
# TODO: service.8
|
||||
|
||||
all: $(BINARIES)
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
$(BINARY): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(OBJS) -o $(BINARY) -lmount $(LIBS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
%: %.c
|
||||
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $< -o $@ -lmount $(LIBS)
|
||||
|
||||
install: all
|
||||
mkdir -p $(DESTDIR)$(SBINDIR)
|
||||
install $(BINARY) $(DESTDIR)$(SBINDIR)
|
||||
install $(BINARIES) $(DESTDIR)$(SBINDIR)
|
||||
mkdir -p $(DESTDIR)$(MANDIR)/man8
|
||||
cp init.8 $(DESTDIR)$(MANDIR)/man8/init.8
|
||||
install $(MANPAGES8) $(DESTDIR)$(MANDIR)/man8
|
||||
|
||||
clean:
|
||||
rm -f $(BINARY) $(OBJS) *.o
|
||||
rm -f $(BINARIES) $(OBJS) *.o
|
||||
|
|
805
init/init.c
805
init/init.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2023 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011-2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -20,8 +20,10 @@
|
|||
#include <sys/display.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -137,6 +139,7 @@ struct dependency
|
|||
#define DEPENDENCY_FLAG_REQUIRE (1 << 0)
|
||||
#define DEPENDENCY_FLAG_AWAIT (1 << 1)
|
||||
#define DEPENDENCY_FLAG_EXIT_CODE (1 << 2)
|
||||
#define DEPENDENCY_FLAG_REFERENCED (1 << 30)
|
||||
|
||||
enum log_method
|
||||
{
|
||||
|
@ -223,7 +226,7 @@ struct daemon
|
|||
bool need_tty;
|
||||
bool was_ready;
|
||||
bool was_terminated;
|
||||
bool was_dereferenced;
|
||||
bool want_restart;
|
||||
bool timeout_set;
|
||||
};
|
||||
|
||||
|
@ -255,6 +258,45 @@ struct daemon_config
|
|||
mode_t log_file_mode;
|
||||
};
|
||||
|
||||
struct server
|
||||
{
|
||||
size_t index;
|
||||
const char* path;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct connection
|
||||
{
|
||||
size_t index;
|
||||
char* input;
|
||||
size_t input_used;
|
||||
size_t input_size;
|
||||
char* output;
|
||||
size_t output_used;
|
||||
size_t output_size;
|
||||
int fd;
|
||||
};
|
||||
|
||||
enum communication_type
|
||||
{
|
||||
COMMUNICATION_TYPE_OUTPUT,
|
||||
COMMUNICATION_TYPE_READY,
|
||||
COMMUNICATION_TYPE_SERVER,
|
||||
COMMUNICATION_TYPE_CONNECTION,
|
||||
};
|
||||
|
||||
struct communication
|
||||
{
|
||||
enum communication_type type;
|
||||
size_t* index_ptr;
|
||||
union
|
||||
{
|
||||
struct daemon* daemon;
|
||||
struct connection* connection;
|
||||
struct server* server;
|
||||
};
|
||||
};
|
||||
|
||||
static pid_t main_pid;
|
||||
static pid_t forward_signal_pid = -1;
|
||||
|
||||
|
@ -297,8 +339,8 @@ static struct pollfd* pfds = NULL;
|
|||
static size_t pfds_used = 0;
|
||||
static size_t pfds_length = 0;
|
||||
|
||||
static struct daemon** pfds_daemon = NULL;
|
||||
static size_t pfds_daemon_length = 0;
|
||||
static struct communication* communications = NULL;
|
||||
static size_t communications_length = 0;
|
||||
|
||||
static bool chain_location_made = false;
|
||||
static char chain_location[] = "/tmp/fs.XXXXXX";
|
||||
|
@ -831,6 +873,12 @@ static void log_status(const char* status, const char* format, ...)
|
|||
fprintf(stderr, "[\e[91mFAILED\e[m] ");
|
||||
else if ( !strcmp(status, "stopping") )
|
||||
fprintf(stderr, "[ ] ");
|
||||
else if ( !strcmp(status, "klling") )
|
||||
fprintf(stderr, "[ ] ");
|
||||
else if ( !strcmp(status, "restart") )
|
||||
fprintf(stderr, "[ ] ");
|
||||
else if ( !strcmp(status, "restarting") )
|
||||
fprintf(stderr, "[ ] ");
|
||||
else if ( !strcmp(status, "stopped") )
|
||||
fprintf(stderr, "[ \e[92mOK\e[m ] ");
|
||||
else if ( !strcmp(status, "timeout") )
|
||||
|
@ -1557,6 +1605,68 @@ static struct daemon_config* daemon_config_load(const char* name)
|
|||
return daemon_config;
|
||||
}
|
||||
|
||||
static bool communication_reserve(size_t required)
|
||||
{
|
||||
if ( pfds_length - pfds_used < required )
|
||||
{
|
||||
size_t old_length = pfds_length ? pfds_length : required;
|
||||
struct pollfd* new_pfds =
|
||||
reallocarray(pfds, old_length, 2 * sizeof(struct pollfd));
|
||||
if ( !new_pfds )
|
||||
return false;
|
||||
pfds = new_pfds;
|
||||
pfds_length = old_length * 2;
|
||||
}
|
||||
if ( communications_length - pfds_used < required )
|
||||
{
|
||||
size_t old_length =
|
||||
communications_length ? communications_length : required;
|
||||
struct communication* new_communications =
|
||||
reallocarray(communications, old_length,
|
||||
2 * sizeof(struct communication));
|
||||
if ( !new_communications )
|
||||
return false;
|
||||
communications = new_communications;
|
||||
communications_length = old_length * 2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void communication_register(struct communication* comm,
|
||||
int fd,
|
||||
short events)
|
||||
{
|
||||
assert(pfds_used < pfds_length);
|
||||
assert(pfds_used < communications_length);
|
||||
size_t index = pfds_used++;
|
||||
struct pollfd* pfd = pfds + index;
|
||||
memset(pfd, 0, sizeof(*pfd));
|
||||
pfd->fd = fd;
|
||||
pfd->events = events;
|
||||
communications[index] = *comm;
|
||||
*communications[index].index_ptr = index;
|
||||
}
|
||||
|
||||
static void communication_unregister(size_t index)
|
||||
{
|
||||
assert(pfds_used <= pfds_length);
|
||||
assert(pfds_used <= communications_length);
|
||||
assert(index < pfds_used);
|
||||
assert(index < communications_length);
|
||||
// This function is relied on to not mess with any pollfds prior to the
|
||||
// index, so it doesn't break a forward iteration on the pollfds.
|
||||
size_t last_index = pfds_used - 1;
|
||||
if ( index != last_index )
|
||||
{
|
||||
memcpy(pfds + index, pfds + last_index, sizeof(*pfds));
|
||||
communications[index] = communications[last_index];
|
||||
*communications[index].index_ptr = index;
|
||||
}
|
||||
pfds_used--;
|
||||
memset(pfds + last_index, 0, sizeof(*pfds));
|
||||
communications[last_index].daemon = NULL;
|
||||
}
|
||||
|
||||
// TODO: Replace with better data structure.
|
||||
static struct daemon* add_daemon(void)
|
||||
{
|
||||
|
@ -1662,6 +1772,27 @@ static struct daemon* daemon_create_unconfigured(const char* name)
|
|||
return daemon;
|
||||
}
|
||||
|
||||
static struct daemon* daemon_find_or_create(const char* name)
|
||||
{
|
||||
// TODO: What happens for virtual daemons?
|
||||
struct daemon* daemon = daemon_find_by_name(name);
|
||||
// TODO: non-fatal daemon_create_unconfigured
|
||||
if ( !daemon )
|
||||
daemon = daemon_create_unconfigured(name);
|
||||
return daemon;
|
||||
}
|
||||
|
||||
static struct dependency* daemon_find_dependency(struct daemon* daemon,
|
||||
const char* target)
|
||||
{
|
||||
for ( size_t i = 0; i < daemon->dependencies_used; i++ )
|
||||
{
|
||||
if ( !strcmp(daemon->dependencies[i]->target->name, target) )
|
||||
return daemon->dependencies[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool daemon_add_dependency(struct daemon* daemon,
|
||||
struct daemon* target,
|
||||
int flags)
|
||||
|
@ -1692,6 +1823,7 @@ static bool daemon_add_dependency(struct daemon* daemon,
|
|||
if ( flags & DEPENDENCY_FLAG_EXIT_CODE )
|
||||
daemon->exit_code_from = dependency;
|
||||
target->reference_count++;
|
||||
dependency->flags |= DEPENDENCY_FLAG_REFERENCED;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1798,12 +1930,73 @@ static struct daemon* daemon_create(struct daemon_config* daemon_config)
|
|||
return daemon;
|
||||
}
|
||||
|
||||
static void schedule_daemon(struct daemon* daemon)
|
||||
static void daemon_schedule(struct daemon* daemon)
|
||||
{
|
||||
assert(daemon->state == DAEMON_STATE_TERMINATED);
|
||||
daemon_change_state_list(daemon, DAEMON_STATE_SCHEDULED);
|
||||
}
|
||||
|
||||
// TODO: Untagle recursion.
|
||||
static void daemon_on_finished(struct daemon* daemon);
|
||||
|
||||
static void daemon_terminate(struct daemon* daemon)
|
||||
{
|
||||
if ( daemon->state != DAEMON_STATE_SCHEDULED &&
|
||||
daemon->state != DAEMON_STATE_SATISFIED &&
|
||||
daemon->state != DAEMON_STATE_STARTING &&
|
||||
daemon->state != DAEMON_STATE_RUNNING )
|
||||
return;
|
||||
if ( daemon->was_terminated )
|
||||
return;
|
||||
daemon->was_terminated = true;
|
||||
daemon->want_restart = false;
|
||||
daemon_change_state_list(daemon, DAEMON_STATE_TERMINATING);
|
||||
if ( 0 < daemon->pid )
|
||||
{
|
||||
log_status("stopping", "Stopping %s...\n", daemon->name);
|
||||
kill(daemon->pid, SIGTERM);
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
daemon->timeout = timespec_add(now, timespec_make(30, 0));
|
||||
daemon->timeout_set = true;
|
||||
}
|
||||
else
|
||||
daemon_on_finished(daemon);
|
||||
}
|
||||
|
||||
static void daemon_request_restart(struct daemon* daemon)
|
||||
{
|
||||
if ( !daemon->reference_count )
|
||||
return;
|
||||
if ( daemon->state == DAEMON_STATE_TERMINATED ||
|
||||
daemon->state == DAEMON_STATE_SCHEDULED ||
|
||||
daemon->state == DAEMON_STATE_WAITING ||
|
||||
daemon->state == DAEMON_STATE_SATISFIED )
|
||||
return;
|
||||
if ( !daemon->want_restart )
|
||||
{
|
||||
log_status("restart", "Restart requested of %s.\n", daemon->name);
|
||||
if ( daemon->state == DAEMON_STATE_STARTING ||
|
||||
daemon->state == DAEMON_STATE_RUNNING )
|
||||
daemon_terminate(daemon);
|
||||
daemon->want_restart = true;
|
||||
}
|
||||
if ( daemon->state == DAEMON_STATE_FINISHED ||
|
||||
daemon->state == DAEMON_STATE_FINISHED )
|
||||
{
|
||||
log_status("restarting", "Restarting %s.\n", daemon->name);
|
||||
daemon_change_state_list(daemon, DAEMON_STATE_SCHEDULED);
|
||||
// TODO: Update dependencies_ready.
|
||||
// TODO: Update dependencies_finished.
|
||||
// TODO: Update dependencies_failed.
|
||||
daemon->was_ready = false;
|
||||
daemon->was_terminated = false;
|
||||
daemon->want_restart = false;
|
||||
// TODO: was_dereferenced?
|
||||
daemon->timeout_set = false; // TODO: Reset before going to FINISHING.
|
||||
}
|
||||
}
|
||||
|
||||
static void daemon_on_finished(struct daemon* daemon)
|
||||
{
|
||||
assert(daemon->state != DAEMON_STATE_FINISHING);
|
||||
|
@ -1815,17 +2008,36 @@ static void daemon_on_finished(struct daemon* daemon)
|
|||
else
|
||||
log_status("finished", "Finished %s.\n", daemon->name);
|
||||
daemon_change_state_list(daemon, DAEMON_STATE_FINISHING);
|
||||
if ( daemon->want_restart )
|
||||
daemon_request_restart(daemon);
|
||||
}
|
||||
|
||||
static void daemon_terminate(struct daemon* daemon)
|
||||
static void daemon_request_start(struct daemon* daemon)
|
||||
{
|
||||
assert(!daemon->was_terminated);
|
||||
if ( daemon->state == DAEMON_STATE_TERMINATED )
|
||||
daemon_schedule(daemon);
|
||||
else if ( daemon->state == DAEMON_STATE_TERMINATING ||
|
||||
daemon->state == DAEMON_STATE_FINISHING ||
|
||||
daemon->state == DAEMON_STATE_FINISHED )
|
||||
daemon_request_restart(daemon);
|
||||
}
|
||||
|
||||
static void daemon_kill(struct daemon* daemon)
|
||||
{
|
||||
if ( daemon->state != DAEMON_STATE_SCHEDULED &&
|
||||
daemon->state != DAEMON_STATE_SATISFIED &&
|
||||
daemon->state != DAEMON_STATE_STARTING &&
|
||||
daemon->state != DAEMON_STATE_RUNNING &&
|
||||
daemon->state != DAEMON_STATE_TERMINATING )
|
||||
return;
|
||||
daemon->was_terminated = true;
|
||||
daemon->want_restart = false;
|
||||
daemon_change_state_list(daemon, DAEMON_STATE_TERMINATING);
|
||||
if ( 0 < daemon->pid )
|
||||
{
|
||||
log_status("stopping", "Stopping %s.\n", daemon->name);
|
||||
kill(daemon->pid, SIGTERM);
|
||||
log_status("killing", "Killing %s.\n", daemon->name);
|
||||
kill(daemon->pid, SIGKILL);
|
||||
// TODO: Is this needed? Or better to do with zero timeout?
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
daemon->timeout = timespec_add(now, timespec_make(30, 0));
|
||||
|
@ -1835,9 +2047,22 @@ static void daemon_terminate(struct daemon* daemon)
|
|||
daemon_on_finished(daemon);
|
||||
}
|
||||
|
||||
static void daemon_reload(struct daemon* daemon)
|
||||
{
|
||||
// TODO: If starting, schedule reload upon RUNNING.
|
||||
if ( daemon->state != DAEMON_STATE_RUNNING )
|
||||
return;
|
||||
if ( 0 < daemon->pid )
|
||||
{
|
||||
log_status("reload", "Reloading %s.\n", daemon->name);
|
||||
kill(daemon->pid, SIGHUP); // TODO: Configuration.
|
||||
}
|
||||
}
|
||||
|
||||
static void daemon_on_not_referenced(struct daemon* daemon)
|
||||
{
|
||||
assert(daemon->reference_count == 0);
|
||||
daemon->want_restart = false;
|
||||
switch ( daemon->state )
|
||||
{
|
||||
case DAEMON_STATE_TERMINATED:
|
||||
|
@ -1867,12 +2092,19 @@ static void daemon_dereference(struct daemon* daemon)
|
|||
daemon_on_not_referenced(daemon);
|
||||
}
|
||||
|
||||
static void daemon_dereference_dependency(struct dependency* dependency)
|
||||
{
|
||||
if ( dependency->flags & DEPENDENCY_FLAG_REFERENCED )
|
||||
{
|
||||
daemon_dereference(dependency->target);
|
||||
dependency->flags &= ~(DEPENDENCY_FLAG_REFERENCED);
|
||||
}
|
||||
}
|
||||
|
||||
static void daemon_dereference_dependencies(struct daemon* daemon)
|
||||
{
|
||||
assert(!daemon->was_dereferenced);
|
||||
daemon->was_dereferenced = true;
|
||||
for ( size_t i = 0; i < daemon->dependencies_used; i++ )
|
||||
daemon_dereference(daemon->dependencies[i]->target);
|
||||
daemon_dereference_dependency(daemon->dependencies[i]);
|
||||
}
|
||||
|
||||
static void daemon_on_dependency_ready(struct dependency* dependency)
|
||||
|
@ -1935,12 +2167,108 @@ static void daemon_on_dependency_finished(struct dependency* dependency)
|
|||
daemon_on_finished(daemon);
|
||||
}
|
||||
|
||||
static bool daemon_depend(struct daemon* source,
|
||||
struct daemon* target,
|
||||
int flags,
|
||||
bool ensure_start)
|
||||
{
|
||||
struct dependency* dependency =
|
||||
daemon_find_dependency(source, target->name);
|
||||
if ( dependency )
|
||||
{
|
||||
// TODO: Updating the flags could be tricky and unsafe.
|
||||
return true;
|
||||
}
|
||||
else if ( !daemon_add_dependency(source, target, flags) )
|
||||
return false;
|
||||
// No need to start the target if the source isn't supposed to be running.
|
||||
if ( source->state == DAEMON_STATE_TERMINATED )
|
||||
return true;
|
||||
// No need to start the target if the source is a non-virtual daemon that is
|
||||
// terminating, or a virtual daemon with exit-code that is terminating.
|
||||
if ( (source->argv || source->exit_code_from) &&
|
||||
(source->state == DAEMON_STATE_TERMINATING ||
|
||||
source->state == DAEMON_STATE_FINISHING ||
|
||||
source->state == DAEMON_STATE_FINISHED) )
|
||||
return true;
|
||||
// No need to start the target if it is finishing, unless we are asked to
|
||||
// ensure it is started up again.
|
||||
// TODO: ensure_start can be always true once there's a proper one shot
|
||||
// vs persistent daemon concept.
|
||||
if ( !ensure_start &&
|
||||
(target->state == DAEMON_STATE_TERMINATING ||
|
||||
target->state == DAEMON_STATE_FINISHING ||
|
||||
target->state == DAEMON_STATE_FINISHED) )
|
||||
return true;
|
||||
if ( target->state == DAEMON_STATE_TERMINATED ||
|
||||
target->state == DAEMON_STATE_TERMINATING ||
|
||||
target->state == DAEMON_STATE_FINISHING ||
|
||||
target->state == DAEMON_STATE_FINISHED )
|
||||
daemon_request_start(target);
|
||||
if ( (target->state == DAEMON_STATE_TERMINATED ||
|
||||
target->state == DAEMON_STATE_SCHEDULED ||
|
||||
target->state == DAEMON_STATE_WAITING) )
|
||||
{
|
||||
if ( source->state == DAEMON_STATE_SATISFIED )
|
||||
daemon_change_state_list(target, DAEMON_STATE_WAITING);
|
||||
else if ( source->state == DAEMON_STATE_TERMINATING ||
|
||||
source->state == DAEMON_STATE_FINISHING ||
|
||||
source->state == DAEMON_STATE_FINISHED )
|
||||
{
|
||||
// TODO: Propagate recursive dependents to RUNNING.
|
||||
// TODO: dependencies_finished and such
|
||||
daemon_change_state_list(source, DAEMON_STATE_RUNNING);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void daemon_undepend(struct daemon* source,
|
||||
struct daemon* target,
|
||||
bool ensure_stop)
|
||||
{
|
||||
for ( size_t i = 0; i < source->dependencies_used; i++ )
|
||||
{
|
||||
if ( source->dependencies[i]->target != target )
|
||||
continue;
|
||||
struct dependency* dependency = source->dependencies[i];
|
||||
size_t last = --source->dependencies_used;
|
||||
if ( i != last )
|
||||
source->dependencies[i] = source->dependencies[last];
|
||||
for ( size_t n = 0; n < target->dependents_used; n++ )
|
||||
{
|
||||
if ( target->dependents[n] != dependency )
|
||||
continue;
|
||||
last = --target->dependents_used;
|
||||
if ( n != last )
|
||||
target->dependents[n] = target->dependents[last];
|
||||
break;
|
||||
}
|
||||
daemon_dereference_dependency(dependency);
|
||||
free(dependency);
|
||||
// TODO: Correct dependencies_ready.
|
||||
// TODO: Correct dependencies_finished.
|
||||
// TODO: Correct dependencies_failed.
|
||||
// TODO: State transition if now SATISFIED or FINISHED.
|
||||
break;
|
||||
}
|
||||
if ( ensure_stop &&
|
||||
(target->state == DAEMON_STATE_STARTING ||
|
||||
target->state == DAEMON_STATE_RUNNING) )
|
||||
daemon_terminate(target);
|
||||
}
|
||||
|
||||
static void daemon_finish(struct daemon* daemon)
|
||||
{
|
||||
assert(daemon->state != DAEMON_STATE_FINISHED);
|
||||
if ( !daemon->was_ready )
|
||||
daemon_mark_ready(daemon);
|
||||
daemon_change_state_list(daemon, DAEMON_STATE_FINISHED);
|
||||
if ( daemon->want_restart )
|
||||
{
|
||||
daemon_request_restart(daemon);
|
||||
return;
|
||||
}
|
||||
for ( size_t i = 0; i < daemon->dependents_used; i++ )
|
||||
daemon_on_dependency_finished(daemon->dependents[i]);
|
||||
daemon_dereference_dependencies(daemon);
|
||||
|
@ -1951,46 +2279,8 @@ static void daemon_on_startup_error(struct daemon* daemon)
|
|||
assert(daemon->state != DAEMON_STATE_FINISHING);
|
||||
assert(daemon->state != DAEMON_STATE_FINISHED);
|
||||
daemon_change_state_list(daemon, DAEMON_STATE_FINISHING);
|
||||
}
|
||||
|
||||
static void daemon_register_pollfd(struct daemon* daemon,
|
||||
int fd,
|
||||
size_t* out_index,
|
||||
short events)
|
||||
{
|
||||
assert(pfds_used < pfds_length);
|
||||
assert(pfds_used < pfds_daemon_length);
|
||||
size_t index = pfds_used++;
|
||||
struct pollfd* pfd = pfds + index;
|
||||
memset(pfd, 0, sizeof(*pfd));
|
||||
pfd->fd = fd;
|
||||
pfd->events = events;
|
||||
pfds_daemon[index] = daemon;
|
||||
*out_index = index;
|
||||
}
|
||||
|
||||
static void daemon_unregister_pollfd(struct daemon* daemon, size_t index)
|
||||
{
|
||||
assert(pfds_used <= pfds_length);
|
||||
assert(index < pfds_used);
|
||||
assert(pfds_daemon[index] == daemon);
|
||||
// This function is relied on to not mess with any pollfds prior to the
|
||||
// index, so it doesn't break a forward iteration on the pollfds.
|
||||
size_t last_index = pfds_used - 1;
|
||||
if ( index != last_index )
|
||||
{
|
||||
memcpy(pfds + index, pfds + last_index, sizeof(*pfds));
|
||||
pfds_daemon[index] = pfds_daemon[last_index];
|
||||
if ( 0 <= pfds_daemon[index]->readyfd &&
|
||||
pfds_daemon[index]->pfd_readyfd_index == last_index )
|
||||
pfds_daemon[index]->pfd_readyfd_index = index;
|
||||
if ( 0 <= pfds_daemon[index]->outputfd &&
|
||||
pfds_daemon[index]->pfd_outputfd_index == last_index )
|
||||
pfds_daemon[index]->pfd_outputfd_index = index;
|
||||
}
|
||||
pfds_used--;
|
||||
memset(pfds + last_index, 0, sizeof(*pfds));
|
||||
pfds_daemon[last_index] = NULL;
|
||||
if ( daemon->want_restart )
|
||||
daemon_request_restart(daemon);
|
||||
}
|
||||
|
||||
static void daemon_wait(struct daemon* daemon)
|
||||
|
@ -2024,7 +2314,7 @@ static void daemon_wait(struct daemon* daemon)
|
|||
switch ( dependency->target->state )
|
||||
{
|
||||
case DAEMON_STATE_TERMINATED:
|
||||
schedule_daemon(dependency->target);
|
||||
daemon_schedule(dependency->target);
|
||||
if ( !(dependency->flags & DEPENDENCY_FLAG_AWAIT) )
|
||||
daemon_on_dependency_ready(dependency);
|
||||
break;
|
||||
|
@ -2104,29 +2394,8 @@ static void daemon_start(struct daemon* daemon)
|
|||
int readyfds[2];
|
||||
if ( !daemon->need_tty )
|
||||
{
|
||||
size_t required_fds = 2;
|
||||
if ( pfds_length - pfds_used < required_fds )
|
||||
{
|
||||
size_t old_length = pfds_length ? pfds_length : required_fds;
|
||||
struct pollfd* new_pfds =
|
||||
reallocarray(pfds, old_length, 2 * sizeof(struct pollfd));
|
||||
if ( !new_pfds )
|
||||
fatal("malloc");
|
||||
pfds = new_pfds;
|
||||
pfds_length = old_length * 2;
|
||||
}
|
||||
if ( pfds_daemon_length - pfds_used < required_fds )
|
||||
{
|
||||
size_t old_length =
|
||||
pfds_daemon_length ? pfds_daemon_length : required_fds;
|
||||
struct daemon** new_pfds_daemon =
|
||||
reallocarray(pfds_daemon, old_length,
|
||||
2 * sizeof(struct daemon*));
|
||||
if ( !new_pfds_daemon )
|
||||
fatal("malloc");
|
||||
pfds_daemon = new_pfds_daemon;
|
||||
pfds_daemon_length = old_length * 2;
|
||||
}
|
||||
if ( !communication_reserve(2) )
|
||||
fatal("malloc");
|
||||
if ( !log_begin(&daemon->log) )
|
||||
{
|
||||
// TODO: Mode where daemons are stopped if logging fails.
|
||||
|
@ -2136,16 +2405,22 @@ static void daemon_start(struct daemon* daemon)
|
|||
daemon->outputfd = outputfds[0];
|
||||
fcntl(daemon->outputfd, F_SETFL, O_NONBLOCK);
|
||||
// Setup the pollfd for the outputfd.
|
||||
daemon_register_pollfd(daemon, daemon->outputfd,
|
||||
&daemon->pfd_outputfd_index, POLLIN);
|
||||
struct communication output_comm;
|
||||
output_comm.type = COMMUNICATION_TYPE_OUTPUT;
|
||||
output_comm.index_ptr = &daemon->pfd_outputfd_index;
|
||||
output_comm.daemon = daemon;
|
||||
communication_register(&output_comm, daemon->outputfd, POLLIN);
|
||||
// Create the readyfd.
|
||||
if ( pipe(readyfds) < 0 )
|
||||
fatal("pipe");
|
||||
daemon->readyfd = readyfds[0];
|
||||
fcntl(daemon->readyfd, F_SETFL, O_NONBLOCK);
|
||||
// Setup the pollfd for the readyfd.
|
||||
daemon_register_pollfd(daemon, daemon->readyfd,
|
||||
&daemon->pfd_readyfd_index, POLLIN);
|
||||
struct communication ready_comm;
|
||||
ready_comm.type = COMMUNICATION_TYPE_READY;
|
||||
ready_comm.index_ptr = &daemon->pfd_readyfd_index;
|
||||
ready_comm.daemon = daemon;
|
||||
communication_register(&ready_comm, daemon->readyfd, POLLIN);
|
||||
}
|
||||
// TODO: This is not concurrency safe, build a environment array just for
|
||||
// this daemon.
|
||||
|
@ -2277,6 +2552,18 @@ static bool daemon_process_ready(struct daemon* daemon)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool daemon_on_ready_event(struct daemon* daemon, int revents)
|
||||
{
|
||||
if ( (revents & (POLLIN | POLLHUP)) && !daemon_process_ready(daemon) )
|
||||
{
|
||||
communication_unregister(daemon->pfd_readyfd_index);
|
||||
close(daemon->readyfd);
|
||||
daemon->readyfd = -1;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool daemon_process_output(struct daemon* daemon)
|
||||
{
|
||||
char data[4096];
|
||||
|
@ -2291,6 +2578,18 @@ static bool daemon_process_output(struct daemon* daemon)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool daemon_on_output_event(struct daemon* daemon, int revents)
|
||||
{
|
||||
if ( (revents & (POLLIN | POLLHUP)) && !daemon_process_output(daemon) )
|
||||
{
|
||||
communication_unregister(daemon->pfd_outputfd_index);
|
||||
close(daemon->outputfd);
|
||||
daemon->outputfd = -1;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void daemon_on_exit(struct daemon* daemon, int exit_code)
|
||||
{
|
||||
assert(daemon->state != DAEMON_STATE_FINISHING);
|
||||
|
@ -2298,14 +2597,14 @@ static void daemon_on_exit(struct daemon* daemon, int exit_code)
|
|||
daemon->exit_code = exit_code;
|
||||
if ( 0 <= daemon->readyfd )
|
||||
{
|
||||
daemon_unregister_pollfd(daemon, daemon->pfd_readyfd_index);
|
||||
communication_unregister(daemon->pfd_readyfd_index);
|
||||
close(daemon->readyfd);
|
||||
daemon->readyfd = -1;
|
||||
}
|
||||
if ( 0 <= daemon->outputfd )
|
||||
{
|
||||
daemon_process_output(daemon);
|
||||
daemon_unregister_pollfd(daemon, daemon->pfd_outputfd_index);
|
||||
communication_unregister(daemon->pfd_outputfd_index);
|
||||
close(daemon->outputfd);
|
||||
daemon->outputfd = -1;
|
||||
}
|
||||
|
@ -2329,6 +2628,293 @@ static void daemon_on_exit(struct daemon* daemon, int exit_code)
|
|||
daemon_on_finished(daemon);
|
||||
}
|
||||
|
||||
static void request_require(int argc, char** argv)
|
||||
{
|
||||
if ( argc < 3 )
|
||||
return warning("missing operand");
|
||||
const char* source_name = argv[1];
|
||||
const char* target_name = argv[2];
|
||||
bool start = 4 <= argc && !strcmp(argv[3], "start");
|
||||
// TODO: Parse flags.
|
||||
int flags = DEPENDENCY_FLAG_AWAIT;
|
||||
struct daemon* source = daemon_find_by_name(source_name);
|
||||
if ( !source )
|
||||
return warning("no %s", source_name);
|
||||
if ( source->argv )
|
||||
return warning("source had argv");
|
||||
struct daemon* target = daemon_find_or_create(target_name);
|
||||
if ( !target )
|
||||
return warning("failed to create %s", target_name);
|
||||
if ( !daemon_depend(source, target, flags, start) )
|
||||
return warning("failed to depend %s -> %s", source_name, target_name);
|
||||
}
|
||||
|
||||
static void request_unrequire(int argc, char** argv)
|
||||
{
|
||||
if ( argc < 3 )
|
||||
return warning("missing operand");
|
||||
const char* source_name = argv[1];
|
||||
const char* target_name = argv[2];
|
||||
bool stop = 4 <= argc && !strcmp(argv[3], "stop");
|
||||
struct daemon* source = daemon_find_by_name(source_name);
|
||||
if ( !source )
|
||||
return warning("no %s", source_name);
|
||||
struct daemon* target = daemon_find_by_name(target_name);
|
||||
if ( !target )
|
||||
return warning("no such daemon running: %s", target_name);
|
||||
daemon_undepend(source, target, stop);
|
||||
}
|
||||
|
||||
static void request_reload(int argc, char** argv)
|
||||
{
|
||||
if ( argc != 2 )
|
||||
return warning("missing operand");
|
||||
const char* name = argv[1];
|
||||
struct daemon* daemon = daemon_find_or_create(name);
|
||||
if ( !daemon )
|
||||
return warning("no %s", name);
|
||||
daemon_reload(daemon);
|
||||
}
|
||||
|
||||
static void request_restart(int argc, char** argv)
|
||||
{
|
||||
if ( argc != 2 )
|
||||
return warning("missing operand");
|
||||
const char* name = argv[1];
|
||||
struct daemon* daemon = daemon_find_or_create(name);
|
||||
if ( !daemon )
|
||||
return warning("no %s", name);
|
||||
daemon_request_restart(daemon);
|
||||
}
|
||||
|
||||
static void request_terminate(int argc, char** argv)
|
||||
{
|
||||
if ( argc != 2 )
|
||||
return warning("missing operand");
|
||||
const char* name = argv[1];
|
||||
struct daemon* daemon = daemon_find_by_name(name);
|
||||
if ( !daemon )
|
||||
return warning("no %s", name);
|
||||
daemon_terminate(daemon);
|
||||
}
|
||||
|
||||
static void request_kill(int argc, char** argv)
|
||||
{
|
||||
if ( argc != 2 )
|
||||
return warning("missing operand");
|
||||
const char* name = argv[1];
|
||||
struct daemon* daemon = daemon_find_by_name(name);
|
||||
if ( !daemon )
|
||||
return warning("no %s", name);
|
||||
daemon_kill(daemon);
|
||||
}
|
||||
|
||||
static void connection_free(struct connection* conn)
|
||||
{
|
||||
free(conn->input);
|
||||
free(conn->output);
|
||||
free(conn);
|
||||
}
|
||||
|
||||
static void connection_close(struct connection* conn)
|
||||
{
|
||||
communication_unregister(conn->index);
|
||||
close(conn->fd);
|
||||
conn->fd = -1;
|
||||
connection_free(conn);
|
||||
}
|
||||
|
||||
static struct connection* connection_new(int fd)
|
||||
{
|
||||
size_t buffer_size = 4096;
|
||||
struct connection* conn = calloc(1, sizeof(struct connection));
|
||||
char* input = malloc(buffer_size);
|
||||
char* output = malloc(buffer_size);
|
||||
if ( !conn || !input || !output )
|
||||
{
|
||||
free(conn);
|
||||
free(input);
|
||||
free(output);
|
||||
return NULL;
|
||||
}
|
||||
conn->input = input;
|
||||
conn->input_used = 0;
|
||||
conn->input_size = buffer_size;
|
||||
conn->output = output;
|
||||
conn->output_used = 0;
|
||||
conn->output_size = buffer_size;
|
||||
conn->fd = fd;
|
||||
if ( !communication_reserve(1) )
|
||||
return connection_free(conn), NULL;
|
||||
struct communication comm;
|
||||
comm.type = COMMUNICATION_TYPE_CONNECTION;
|
||||
comm.index_ptr = &conn->index;
|
||||
comm.connection = conn;
|
||||
communication_register(&comm, fd, POLLIN);
|
||||
return conn;
|
||||
}
|
||||
|
||||
static void connection_on_message(struct connection* conn, const char* message)
|
||||
{
|
||||
(void) conn; // TODO: Reply.
|
||||
|
||||
size_t argc = 0;
|
||||
char** argv = tokenize(&argc, message);
|
||||
if ( !argv )
|
||||
{
|
||||
if ( !errno )
|
||||
/* TODO: syntax error */{}
|
||||
else
|
||||
/* TODO: other error */{}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( argc == 0 ) {}
|
||||
else if ( !strcmp(argv[0], "require") )
|
||||
request_require(argc, argv);
|
||||
else if ( !strcmp(argv[0], "unrequire") )
|
||||
request_unrequire(argc, argv);
|
||||
else if ( !strcmp(argv[0], "reload") )
|
||||
request_reload(argc, argv);
|
||||
else if ( !strcmp(argv[0], "restart") )
|
||||
request_restart(argc, argv);
|
||||
else if ( !strcmp(argv[0], "terminate") )
|
||||
request_terminate(argc, argv);
|
||||
else if ( !strcmp(argv[0], "kill") )
|
||||
request_kill(argc, argv);
|
||||
else
|
||||
warning("%s", message);
|
||||
|
||||
for ( size_t i = 0; i < argc; i++ )
|
||||
free(argv[i]);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
static bool connection_on_event(struct connection* conn, int revents)
|
||||
{
|
||||
// TODO: POLLHUP and POLLERR.
|
||||
if ( (revents & POLLIN) && conn->input_used < conn->input_size )
|
||||
{
|
||||
ssize_t amount = recv(conn->fd, conn->input + conn->input_used,
|
||||
conn->input_size - conn->input_used, 0);
|
||||
if ( 0 < amount )
|
||||
{
|
||||
size_t i = conn->input_used;
|
||||
conn->input_used += amount;
|
||||
while ( i < conn->input_used )
|
||||
{
|
||||
if ( conn->input[i] == '\n' )
|
||||
{
|
||||
conn->input[i] = '\0';
|
||||
connection_on_message(conn, conn->input);
|
||||
memmove(conn->input, conn->input + i, conn->input_size - i);
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
// Disconnect if the input line is too long.
|
||||
if ( conn->input_used == conn->input_size )
|
||||
{
|
||||
connection_close(conn);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( amount == 0 ||
|
||||
(amount < 0 && errno != EWOULDBLOCK && errno != EAGAIN ) )
|
||||
{
|
||||
connection_close(conn);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( (revents & POLLOUT) && conn->output_used )
|
||||
{
|
||||
ssize_t amount = send(conn->fd, conn->output, conn->output_used,
|
||||
MSG_NOSIGNAL);
|
||||
if ( 0 < amount )
|
||||
{
|
||||
if ( (size_t) amount < conn->output_used )
|
||||
memmove(conn->output, conn->output + amount,
|
||||
conn->output_used - amount);
|
||||
conn->output_used -= amount;
|
||||
}
|
||||
else if ( errno != EWOULDBLOCK && errno != EAGAIN )
|
||||
{
|
||||
connection_close(conn);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( (revents & (POLLHUP | POLLERR)) )
|
||||
{
|
||||
connection_close(conn);
|
||||
return false;
|
||||
}
|
||||
// TODO: Recompute poll bits.
|
||||
return true;
|
||||
}
|
||||
|
||||
static int open_local_server_socket(const char* path, int flags)
|
||||
{
|
||||
size_t path_length = strlen(path);
|
||||
size_t addr_size = offsetof(struct sockaddr_un, sun_path) + path_length + 1;
|
||||
struct sockaddr_un* sockaddr = malloc(addr_size);
|
||||
if ( !sockaddr )
|
||||
return -1;
|
||||
sockaddr->sun_family = AF_LOCAL;
|
||||
strcpy(sockaddr->sun_path, path);
|
||||
int fd = socket(AF_LOCAL, SOCK_STREAM | flags, 0);
|
||||
if ( fd < 0 )
|
||||
return free(sockaddr), -1;
|
||||
if ( fchmod(fd, 0600) < 0 )
|
||||
return close(fd), free(sockaddr), -1;
|
||||
if ( bind(fd, (const struct sockaddr*) sockaddr, addr_size) < 0 )
|
||||
return close(fd), free(sockaddr), -1;
|
||||
if ( listen(fd, SOMAXCONN) < 0 )
|
||||
return close(fd), free(sockaddr), -1;
|
||||
free(sockaddr);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static struct server* server_start(const char* path)
|
||||
{
|
||||
if ( !communication_reserve(1) )
|
||||
return NULL;
|
||||
struct server* server = malloc(sizeof(struct server));
|
||||
if ( !server )
|
||||
return NULL;
|
||||
server->fd = open_local_server_socket(path, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
if ( server->fd < 0 )
|
||||
{
|
||||
free(server);
|
||||
return NULL;
|
||||
}
|
||||
struct communication comm;
|
||||
comm.type = COMMUNICATION_TYPE_SERVER;
|
||||
comm.index_ptr = &server->index;
|
||||
comm.server = server;
|
||||
communication_register(&comm, server->fd, POLLIN);
|
||||
return server;
|
||||
}
|
||||
|
||||
static bool server_on_event(struct server* server, int revents)
|
||||
{
|
||||
if ( revents & POLLIN )
|
||||
{
|
||||
int fd = accept4(server->fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
if ( 0 <= fd )
|
||||
{
|
||||
struct connection* conn = connection_new(fd);
|
||||
if ( !conn )
|
||||
{
|
||||
warning("Failed to allocate connection: %s: %m", server->path);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else if ( errno != EAGAIN && errno != EWOULDBLOCK )
|
||||
warning("accept: %s: %m", server->path);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init(void)
|
||||
{
|
||||
int default_daemon_exit_code = -1;
|
||||
|
@ -2441,39 +3027,25 @@ static void init(void)
|
|||
if ( !pfd->revents )
|
||||
continue;
|
||||
nevents--;
|
||||
struct daemon* daemon = pfds_daemon[i];
|
||||
if ( 0 <= daemon->readyfd && pfd->fd == daemon->readyfd )
|
||||
struct communication* comm = &communications[i];
|
||||
bool closed = false;
|
||||
switch ( comm->type )
|
||||
{
|
||||
if ( pfd->revents & (POLLIN | POLLHUP) )
|
||||
{
|
||||
if ( !daemon_process_ready(daemon) )
|
||||
{
|
||||
daemon_unregister_pollfd(daemon,
|
||||
daemon->pfd_readyfd_index);
|
||||
close(daemon->readyfd);
|
||||
daemon->readyfd = -1;
|
||||
i--; // Process this index again (something new there).
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( 0 <= daemon->outputfd && pfd->fd == daemon->outputfd )
|
||||
{
|
||||
if ( pfd->revents & (POLLIN | POLLHUP) )
|
||||
{
|
||||
if ( !daemon_process_output(daemon) )
|
||||
{
|
||||
daemon_unregister_pollfd(daemon,
|
||||
daemon->pfd_outputfd_index);
|
||||
close(daemon->outputfd);
|
||||
daemon->outputfd = -1;
|
||||
i--; // Process this index again (something new there).
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
case COMMUNICATION_TYPE_OUTPUT:
|
||||
closed = daemon_on_output_event(comm->daemon, pfd->revents);
|
||||
break;
|
||||
case COMMUNICATION_TYPE_READY:
|
||||
closed = daemon_on_ready_event(comm->daemon, pfd->revents);
|
||||
break;
|
||||
case COMMUNICATION_TYPE_SERVER:
|
||||
closed = server_on_event(comm->server, pfd->revents);
|
||||
break;
|
||||
case COMMUNICATION_TYPE_CONNECTION:
|
||||
closed = connection_on_event(comm->connection, pfd->revents);
|
||||
break;
|
||||
}
|
||||
if ( closed )
|
||||
i--; // Process this index again (something new there).
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3683,13 +4255,18 @@ int main(int argc, char* argv[])
|
|||
reinit();
|
||||
}
|
||||
|
||||
// TODO: Avoid conflicts with chroots.
|
||||
const char* server_path = "/var/run/init";
|
||||
if ( !server_start(server_path) )
|
||||
fatal("Failed to start init server: %s: %m", server_path);
|
||||
|
||||
// TODO: Use the arguments to specify additional things the default daemon
|
||||
// should depend on, as well as a denylist of things not to start
|
||||
// even if in default's dependencies. The easiest thing is probably to
|
||||
// be able to inject require and unset require lines into default.
|
||||
|
||||
// Request the default daemon be run.
|
||||
schedule_daemon(default_daemon);
|
||||
daemon_schedule(default_daemon);
|
||||
|
||||
// Initialize the operating system.
|
||||
init();
|
||||
|
|
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* service.c
|
||||
* Start and stop services.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static bool array_add(void*** array_ptr,
|
||||
size_t* used_ptr,
|
||||
size_t* length_ptr,
|
||||
void* value)
|
||||
{
|
||||
void** array;
|
||||
memcpy(&array, array_ptr, sizeof(array)); // Strict aliasing.
|
||||
|
||||
if ( *used_ptr == *length_ptr )
|
||||
{
|
||||
size_t length = *length_ptr;
|
||||
if ( !length )
|
||||
length = 4;
|
||||
void** new_array = reallocarray(array, length, 2 * sizeof(void*));
|
||||
if ( !new_array )
|
||||
return false;
|
||||
array = new_array;
|
||||
memcpy(array_ptr, &array, sizeof(array)); // Strict aliasing.
|
||||
*length_ptr = length * 2;
|
||||
}
|
||||
|
||||
memcpy(array + (*used_ptr)++, &value, sizeof(value)); // Strict aliasing.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static char** tokenize(size_t* out_tokens_used, const char* string)
|
||||
{
|
||||
size_t tokens_used = 0;
|
||||
size_t tokens_length = 0;
|
||||
char** tokens = malloc(sizeof(char*));
|
||||
if ( !tokens )
|
||||
return NULL;
|
||||
bool failed = false;
|
||||
bool invalid = false;
|
||||
while ( *string )
|
||||
{
|
||||
if ( isspace((unsigned char) *string) )
|
||||
{
|
||||
string++;
|
||||
continue;
|
||||
}
|
||||
if ( *string == '#' )
|
||||
break;
|
||||
char* token;
|
||||
size_t token_size;
|
||||
FILE* fp = open_memstream(&token, &token_size);
|
||||
if ( !fp )
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
bool singly = false;
|
||||
bool doubly = false;
|
||||
bool escaped = false;
|
||||
for ( char c = *string++; c; c = *string++ )
|
||||
{
|
||||
if ( !escaped && !singly && !doubly && isspace((unsigned char) c) )
|
||||
break;
|
||||
if ( !escaped && !doubly && c == '\'' )
|
||||
{
|
||||
singly = !singly;
|
||||
continue;
|
||||
}
|
||||
if ( !escaped && !singly && c == '"' )
|
||||
{
|
||||
doubly = !doubly;
|
||||
continue;
|
||||
}
|
||||
if ( !singly && !escaped && c == '\\' )
|
||||
{
|
||||
escaped = true;
|
||||
continue;
|
||||
}
|
||||
if ( escaped )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'a': c = '\a'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'e': c = '\e'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
default: break;
|
||||
};
|
||||
}
|
||||
escaped = false;
|
||||
if ( fputc((unsigned char) c, fp) == EOF )
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( singly || doubly || escaped )
|
||||
{
|
||||
fclose(fp);
|
||||
free(token);
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
if ( fflush(fp) == EOF )
|
||||
{
|
||||
fclose(fp);
|
||||
free(token);
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
if ( !array_add((void***) &tokens, &tokens_used, &tokens_length,
|
||||
token) )
|
||||
{
|
||||
free(token);
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( failed || invalid )
|
||||
{
|
||||
for ( size_t i = 0; i < tokens_used; i++ )
|
||||
free(tokens[i]);
|
||||
free(tokens);
|
||||
if ( invalid )
|
||||
errno = 0;
|
||||
return NULL;
|
||||
}
|
||||
char** new_tokens = reallocarray(tokens, tokens_used, sizeof(char*));
|
||||
if ( new_tokens )
|
||||
tokens = new_tokens;
|
||||
*out_tokens_used = tokens_used;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static int open_local_client_socket(const char* path, int flags)
|
||||
{
|
||||
size_t path_length = strlen(path);
|
||||
size_t addr_size = offsetof(struct sockaddr_un, sun_path) + path_length + 1;
|
||||
struct sockaddr_un* sockaddr = malloc(addr_size);
|
||||
if ( !sockaddr )
|
||||
return -1;
|
||||
sockaddr->sun_family = AF_LOCAL;
|
||||
strcpy(sockaddr->sun_path, path);
|
||||
int fd = socket(AF_LOCAL, SOCK_STREAM | flags, 0);
|
||||
if ( fd < 0 )
|
||||
return free(sockaddr), -1;
|
||||
if ( connect(fd, (const struct sockaddr*) sockaddr, addr_size) < 0 )
|
||||
return close(fd), free(sockaddr), -1;
|
||||
free(sockaddr);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void rewrite(const char* path, const char* daemon, const char* flags)
|
||||
{
|
||||
FILE* fp = fopen(path, "r");
|
||||
if ( !fp )
|
||||
{
|
||||
if ( errno != ENOENT )
|
||||
err(1, "%s", path);
|
||||
}
|
||||
char* out_path;
|
||||
if ( asprintf(&out_path, "%s.XXXXXX", path) < 0 )
|
||||
err(1, "malloc");
|
||||
int out_fd = mkstemp(out_path);
|
||||
if ( out_fd < 0 )
|
||||
err(1, "mkstemp: %s.XXXXXX", path);
|
||||
FILE* out = fdopen(out_fd, "w");
|
||||
if ( !out )
|
||||
{
|
||||
unlink(out_path);
|
||||
err(1, "fdopen");
|
||||
}
|
||||
bool found = false;
|
||||
char* line = NULL;
|
||||
size_t line_size = 0;
|
||||
ssize_t line_length;
|
||||
off_t line_number = 0;
|
||||
while ( fp && 0 < (line_length = getline(&line, &line_size, fp)) )
|
||||
{
|
||||
line_number++;
|
||||
size_t tokenc;
|
||||
char** tokens = tokenize(&tokenc, line);
|
||||
if ( !tokens )
|
||||
{
|
||||
unlink(out_path);
|
||||
if ( errno )
|
||||
err(1, "%s", path);
|
||||
else
|
||||
errx(1, "%s:%ji: Syntax error", path, (intmax_t) line_number);
|
||||
}
|
||||
if ( 2 <= tokenc &&
|
||||
!strcmp(tokens[0], "require") && !strcmp(tokens[1], daemon) )
|
||||
{
|
||||
found = true;
|
||||
if ( flags )
|
||||
fprintf(out, "require %s%s\n", daemon, flags);
|
||||
}
|
||||
else
|
||||
fputs(line, out);
|
||||
}
|
||||
free(line);
|
||||
if ( !found && flags )
|
||||
fprintf(out, "require %s%s\n", daemon, flags);
|
||||
if ( (fp && ferror(fp)) || ferror(out) || fflush(out) == EOF )
|
||||
{
|
||||
unlink(out_path);
|
||||
err(1, "%s", path);
|
||||
}
|
||||
if ( fp )
|
||||
{
|
||||
struct stat st;
|
||||
fstat(fileno(fp), &st);
|
||||
fchmod(out_fd, st.st_mode & 07777);
|
||||
fchown(out_fd, st.st_uid, st.st_gid);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
fchmod(out_fd, 0666 & ~getumask());
|
||||
if ( rename(out_path, path) < 0 )
|
||||
{
|
||||
unlink(out_path);
|
||||
err(1, "rename: %s -> %s", out_path, path);
|
||||
}
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
static bool check_daemon_exists_in_dir(const char* dir, const char* daemon)
|
||||
{
|
||||
char* path;
|
||||
if ( asprintf(&path, "%s/%s", dir, daemon) < 0 )
|
||||
err(1, "malloc");
|
||||
bool result = !access(path, F_OK);
|
||||
free(path);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void check_daemon_exists(const char* daemon)
|
||||
{
|
||||
if ( !check_daemon_exists_in_dir("/etc/init", daemon) &&
|
||||
!check_daemon_exists_in_dir("/share/init", daemon) )
|
||||
errx(1, "%s: Daemon does not exist", daemon);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const char* init_socket = getenv("INIT_SOCKET");
|
||||
if ( !init_socket )
|
||||
init_socket = "/var/run/init";
|
||||
|
||||
bool exit_code = false;
|
||||
bool no_await = false;
|
||||
bool optional = true;
|
||||
bool raw = false;
|
||||
const char* source = "local";
|
||||
|
||||
const struct option longopts[] =
|
||||
{
|
||||
{"exit-code", no_argument, NULL, 256},
|
||||
{"no-await", no_argument, NULL, 257},
|
||||
{"no-optional", no_argument, NULL, 258},
|
||||
{"source", required_argument, NULL, 't'},
|
||||
{"raw", no_argument, NULL, 'r'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
const char* opts = "rs:";
|
||||
int opt;
|
||||
while ( (opt = getopt_long(argc, argv, opts, longopts, NULL)) != -1 )
|
||||
{
|
||||
switch ( opt )
|
||||
{
|
||||
case 'r': raw = true; break;
|
||||
case 's': source = optarg; break;
|
||||
case 256: exit_code = true; break;
|
||||
case 257: no_await = true; break;
|
||||
case 258: optional = false; break;
|
||||
default: return 2;
|
||||
}
|
||||
}
|
||||
|
||||
int fd = open_local_client_socket(init_socket, 0);
|
||||
if ( fd < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
|
||||
if ( raw )
|
||||
{
|
||||
for ( int i = optind; i < argc; i++ )
|
||||
{
|
||||
if ( dprintf(fd, "%s%c", argv[i], i + 1 == argc ? '\n' : ' ') < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( argc - optind < 2 )
|
||||
errx(1, "usage: <daemon> <command>");
|
||||
|
||||
const char* daemon = argv[optind++];
|
||||
const char* command = argv[optind++];
|
||||
|
||||
char flags[sizeof(" optional no-await exit-code")];
|
||||
snprintf(flags, sizeof(flags), "%s%s%s",
|
||||
optional ? " optional" : "",
|
||||
no_await ? " no-await" : "",
|
||||
exit_code ? " exit-code" : "");
|
||||
char* source_path;
|
||||
if ( asprintf(&source_path, "/etc/init/%s", source) < 0 )
|
||||
err(1, "malloc");
|
||||
|
||||
if ( !strcmp(command, "enable") )
|
||||
{
|
||||
check_daemon_exists(daemon);
|
||||
rewrite(source_path, daemon, flags);
|
||||
if ( dprintf(fd, "require %s %s start\n", source, daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
else if ( !strcmp(command, "disable") )
|
||||
{
|
||||
rewrite(source_path, daemon, NULL);
|
||||
if ( dprintf(fd, "unrequire %s %s\n", source, daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
else if ( !strcmp(command, "start") )
|
||||
{
|
||||
if ( dprintf(fd, "require %s %s start\n", source, daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
else if ( !strcmp(command, "stop") )
|
||||
{
|
||||
if ( dprintf(fd, "unrequire %s %s\n", source, daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
else if ( !strcmp(command, "restart") )
|
||||
{
|
||||
if ( dprintf(fd, "restart %s\n", daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
else if ( !strcmp(command, "reload") )
|
||||
{
|
||||
if ( dprintf(fd, "reload %s\n", daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
else if ( !strcmp(command, "reconfigure") )
|
||||
{
|
||||
if ( dprintf(fd, "reconfigure %s\n", daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
else if ( !strcmp(command, "terminate") )
|
||||
{
|
||||
if ( dprintf(fd, "terminate %s\n", daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
else if ( !strcmp(command, "kill") )
|
||||
{
|
||||
if ( dprintf(fd, "kill %s\n", daemon) < 0 )
|
||||
err(1, "%s", init_socket);
|
||||
}
|
||||
// TODO: --list
|
||||
// TODO: status
|
||||
// TODO: signal
|
||||
// TODO: pid
|
||||
// TODO: requirements
|
||||
// TODO: log
|
||||
else
|
||||
errx(1, "unknown command: %s", command);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* sortix/types.h
|
||||
* Data types.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SORTIX_TYPES_H
|
||||
#define _INCLUDE_SORTIX_TYPES_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2014, 2016, 2017, 2021, 2022 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2013-2014, 2016-2017, 2021-2022, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -390,6 +390,7 @@ int StreamSocket::getsockopt(ioctx_t* ctx, int level, int option_name,
|
|||
{
|
||||
case SO_RCVBUF: result = incoming.Size(); break;
|
||||
case SO_SNDBUF: result = outgoing.Size(); break;
|
||||
case SO_ERROR: result = 0; break;
|
||||
default: return errno = ENOPROTOOPT, -1; break;
|
||||
}
|
||||
|
||||
|
|
|
@ -547,7 +547,7 @@ ssize_t PTY::master_write(ioctx_t* ctx, const uint8_t* buf, size_t count)
|
|||
{
|
||||
if ( ctx->dflags & O_NONBLOCK )
|
||||
return errno = EWOULDBLOCK, -1;
|
||||
if ( !kthread_cond_wait_signal(&output_ready_cond, &termlock) )
|
||||
if ( !kthread_cond_wait_signal(&output_possible_cond, &termlock) )
|
||||
return errno = EINTR, -1;
|
||||
}
|
||||
size_t sofar = 0;
|
||||
|
|
|
@ -302,8 +302,8 @@ int glob(const char* restrict pattern,
|
|||
const char* path = segment->prefix ? segment->prefix : ".";
|
||||
if ( errno == ENOMEM )
|
||||
result = GLOB_NOSPACE;
|
||||
else if ( (errfunc && errfunc(path, errno)) ||
|
||||
(flags & GLOB_ERR) )
|
||||
else if ( errno && ((errfunc && errfunc(path, errno)) ||
|
||||
(flags & GLOB_ERR)) )
|
||||
result = GLOB_ABORTED;
|
||||
segment->done = true;
|
||||
continue;
|
||||
|
@ -414,7 +414,7 @@ int glob(const char* restrict pattern,
|
|||
free(path);
|
||||
continue;
|
||||
}
|
||||
if ( want_slash && path[size - 3] != '/' )
|
||||
if ( want_slash && is_dir && path[size - 3] != '/' )
|
||||
path[size - 2] = '/', path[size - 1] = '\0';
|
||||
if ( !exists )
|
||||
{
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
diff -Paur --no-dereference -- libsqlite3.upstream/shell.c libsqlite3/shell.c
|
||||
--- libsqlite3.upstream/shell.c
|
||||
+++ libsqlite3/shell.c
|
||||
@@ -150,6 +150,10 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
+#if !defined(FILENAME_MAX) && defined(__sortix__)
|
||||
+#define FILENAME_MAX 256
|
||||
+#endif
|
||||
+
|
||||
#if HAVE_READLINE
|
||||
# include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
@@ -4915,7 +4919,6 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
-#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#ifndef OMIT_BASE85_CHECKER
|
||||
@@ -7540,7 +7543,7 @@
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
-#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
|
||||
+#elif defined(AT_FDCWD)
|
||||
/* Recent unix */
|
||||
struct timespec times[2];
|
||||
times[0].tv_nsec = times[1].tv_nsec = 0;
|
||||
@@ -28955,8 +28958,8 @@
|
||||
#if !defined(_WIN32_WCE)
|
||||
if( getenv("SQLITE_DEBUG_BREAK") ){
|
||||
if( isatty(0) && isatty(2) ){
|
||||
- eputf("attach debugger to process %d and press any key to continue.\n",
|
||||
- GETPID());
|
||||
+ eputf("attach debugger to process %jd and press any key to continue.\n",
|
||||
+ (intmax_t)GETPID());
|
||||
fgetc(stdin);
|
||||
}else{
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
diff -Paur --no-dereference -- libsqlite3.upstream/sqlite3.c libsqlite3/sqlite3.c
|
||||
--- libsqlite3.upstream/sqlite3.c
|
||||
+++ libsqlite3/sqlite3.c
|
||||
@@ -15518,6 +15518,9 @@
|
||||
|
||||
/* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h
|
||||
*/
|
||||
+#if !defined(FILENAME_MAX) && defined(__sortix__)
|
||||
+#define FILENAME_MAX 256
|
||||
+#endif
|
||||
#ifndef SQLITE_MAX_PATHLEN
|
||||
# define SQLITE_MAX_PATHLEN FILENAME_MAX
|
||||
#endif
|
||||
@@ -38135,6 +38138,45 @@
|
||||
# include <sys/param.h>
|
||||
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
|
||||
|
||||
+#ifndef F_SETLK
|
||||
+#define F_SETLK (-1)
|
||||
+#define F_SETLKW (-2)
|
||||
+#define F_GETLK (-3)
|
||||
+#define F_UNLCK 0
|
||||
+#define F_RDLCK 1
|
||||
+#define F_WRLCK 2
|
||||
+struct flock
|
||||
+{
|
||||
+ short l_type;
|
||||
+ short l_whence;
|
||||
+ off_t l_start;
|
||||
+ off_t l_len;
|
||||
+ pid_t l_pid;
|
||||
+};
|
||||
+int fcntl_no_lock(int fd, int cmd, ...)
|
||||
+{
|
||||
+ va_list ap;
|
||||
+ va_start(ap, cmd);
|
||||
+ int result;
|
||||
+ if ( cmd == F_SETLK )
|
||||
+ result = 0;
|
||||
+ else if ( cmd == F_SETLKW )
|
||||
+ result = 0;
|
||||
+ else if ( cmd == F_GETLK )
|
||||
+ {
|
||||
+ struct flock* fl = va_arg(ap, struct flock*);
|
||||
+ fl->l_type = F_UNLCK;
|
||||
+ }
|
||||
+ else if ( cmd == F_SETFD )
|
||||
+ result = fcntl(fd, cmd, va_arg(ap, int));
|
||||
+ else
|
||||
+ result = errno = ENOSYS, -1;
|
||||
+ va_end(ap);
|
||||
+ return result;
|
||||
+}
|
||||
+#define fcntl fcntl_no_lock
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
** Try to determine if gethostuuid() is available based on standard
|
||||
** macros. This might sometimes compute the wrong value for some
|
||||
@@ -39598,6 +39640,7 @@
|
||||
|
||||
/* Otherwise see if some other process holds it.
|
||||
*/
|
||||
+#ifdef F_WRLCK
|
||||
#ifndef __DJGPP__
|
||||
if( !reserved && !pFile->pInode->bProcessLock ){
|
||||
struct flock lock;
|
||||
@@ -39613,6 +39656,7 @@
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+#endif
|
||||
|
||||
sqlite3_mutex_leave(pFile->pInode->pLockMutex);
|
||||
OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
|
||||
@@ -40365,11 +40409,15 @@
|
||||
if( pFile->eFileLock > NO_LOCK ){
|
||||
pFile->eFileLock = eFileLock;
|
||||
/* Always update the timestamp on the old file */
|
||||
+#if defined(__sortix__)
|
||||
+ utimens(zLockFile, NULL);
|
||||
+#else
|
||||
#ifdef HAVE_UTIME
|
||||
utime(zLockFile, NULL);
|
||||
#else
|
||||
utimes(zLockFile, NULL);
|
||||
#endif
|
||||
+#endif
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
NAME=libsqlite3
|
||||
BUILD_LIBRARIES='libcurses? libreadline? libz?'
|
||||
VERSION_YEAR=2024
|
||||
VERSION_MAJOR=3
|
||||
VERSION_MINOR=45
|
||||
VERSION_PATCH=3
|
||||
VERSION=$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH
|
||||
DISTNAME=sqlite-autoconf-${VERSION_MAJOR}${VERSION_MINOR}0${VERSION_PATCH}00
|
||||
COMPRESSION=tar.gz
|
||||
ARCHIVE=$DISTNAME.$COMPRESSION
|
||||
SHA256SUM=b2809ca53124c19c60f42bf627736eae011afdcc205bb48270a5ee9a38191531
|
||||
UPSTREAM_SITE=https://www.sqlite.org/$VERSION_YEAR
|
||||
UPSTREAM_ARCHIVE=$ARCHIVE
|
||||
RELEASE_SEARCH_PAGE=https://www.sqlite.org/download.html
|
||||
RELEASE_SEARCH_REGEX='^PRODUCT,([0-9]+\.[0-9]+\.[0-9]+),'
|
||||
LICENSE=LICENSE=PUBLIC-DOMAIN
|
||||
BUILD_SYSTEM=configure
|
||||
MAKE_VARS='V=1'
|
||||
POST_INSTALL=tix-eradicate-libtool-la
|
|
@ -0,0 +1,840 @@
|
|||
diff -Paur --no-dereference -- php.upstream/Zend/zend_cpuinfo.h php/Zend/zend_cpuinfo.h
|
||||
--- php.upstream/Zend/zend_cpuinfo.h
|
||||
+++ php/Zend/zend_cpuinfo.h
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
#include "zend.h"
|
||||
|
||||
+#if defined(__GNUC__) && 6 < __GNUC__
|
||||
+#define __builtin_cpu_supports(x) 0
|
||||
+#endif
|
||||
+
|
||||
#define ZEND_CPU_EBX_MASK (1<<30)
|
||||
#define ZEND_CPU_EDX_MASK (1U<<31)
|
||||
|
||||
diff -Paur --no-dereference -- php.upstream/Zend/zend_signal.c php/Zend/zend_signal.c
|
||||
--- php.upstream/Zend/zend_signal.c
|
||||
+++ php/Zend/zend_signal.c
|
||||
@@ -64,7 +64,7 @@
|
||||
static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context);
|
||||
static zend_result zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*));
|
||||
|
||||
-#if defined(__CYGWIN__) || defined(__PASE__)
|
||||
+#if defined(__CYGWIN__) || defined(__PASE__) || !defined(SIGPROF)
|
||||
/* Matches zend_execute_API.c; these platforms don't support ITIMER_PROF. */
|
||||
#define TIMEOUT_SIG SIGALRM
|
||||
#else
|
||||
diff -Paur --no-dereference -- php.upstream/build/Makefile.global php/build/Makefile.global
|
||||
--- php.upstream/build/Makefile.global
|
||||
+++ php/build/Makefile.global
|
||||
@@ -1,3 +1,5 @@
|
||||
+INSTALL_ROOT = $(DESTDIR)
|
||||
+
|
||||
mkinstalldirs = $(top_srcdir)/build/shtool mkdir -p
|
||||
INSTALL = $(top_srcdir)/build/shtool install -c
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
@@ -134,6 +136,7 @@
|
||||
rm -f ext/phar/phar/phar.inc; \
|
||||
fi
|
||||
$(EGREP) define'.*include/php' $(top_srcdir)/configure | $(SED) 's/.*>//'|xargs rm -f
|
||||
+ rm -f config.nice sapi/phpdbg/phpdbg sapi/fpm/www.conf
|
||||
|
||||
prof-gen:
|
||||
CCACHE_DISABLE=1 $(MAKE) PROF_FLAGS=-fprofile-generate all
|
||||
diff -Paur --no-dereference -- php.upstream/configure php/configure
|
||||
--- php.upstream/configure
|
||||
+++ php/configure
|
||||
@@ -4456,13 +4456,6 @@
|
||||
case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
|
||||
|
||||
|
||||
-# The aliases save the names the user supplied, while $host etc.
|
||||
-# will get canonicalized.
|
||||
-test -n "$target_alias" &&
|
||||
- test "$program_prefix$program_suffix$program_transform_name" = \
|
||||
- NONENONEs,x,x, &&
|
||||
- program_prefix=${target_alias}-
|
||||
-
|
||||
if test -z "$host_alias" && test -n "$host"; then
|
||||
host_alias=$host
|
||||
fi
|
||||
@@ -18144,7 +18137,9 @@
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
-
|
||||
+ #if defined(__GNUC__) && __GNUC__ < 6
|
||||
+ #error "sortix gcc 5.2.0 has binutils 2.24 which is too old"
|
||||
+ #endif
|
||||
#include <immintrin.h>
|
||||
int main(void) {
|
||||
__m512i mask = _mm512_set1_epi32(0x1);
|
||||
@@ -18183,7 +18178,9 @@
|
||||
CFLAGS="-mavx512f -mavx512cd -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi $CFLAGS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
-
|
||||
+ #if defined(__GNUC__) && __GNUC__ < 6
|
||||
+ #error "sortix gcc 5.2.0 has binutils 2.24 which is too old"
|
||||
+ #endif
|
||||
#include <immintrin.h>
|
||||
int main(void) {
|
||||
__m512i mask = _mm512_set1_epi32(0x1);
|
||||
@@ -19517,7 +19514,7 @@
|
||||
ac_cv_func_getaddrinfo=yes
|
||||
;;
|
||||
*)
|
||||
- ac_cv_func_getaddrinfo=no
|
||||
+ ac_cv_func_getaddrinfo=yes
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -43142,6 +43139,10 @@
|
||||
|
||||
|
||||
|
||||
+# PATCH: Bypass poorly implemented libiconv detection logic.
|
||||
+if [ "$host_os" = sortix ]; then
|
||||
+LIBS="$LIBS -liconv"
|
||||
+fi
|
||||
|
||||
if test "$PHP_ICONV" != "no"; then
|
||||
|
||||
@@ -43151,7 +43152,9 @@
|
||||
|
||||
if test "$PHP_ICONV" = "yes"; then
|
||||
LIBS_save="$LIBS"
|
||||
+ if [ "$host_os" != sortix ]; then
|
||||
LIBS=
|
||||
+ fi
|
||||
ac_fn_c_check_func "$LINENO" "iconv" "ac_cv_func_iconv"
|
||||
if test "x$ac_cv_func_iconv" = xyes
|
||||
then :
|
||||
@@ -98080,7 +98083,8 @@
|
||||
fi;
|
||||
|
||||
all_targets="$lcov_target \$(OVERALL_TARGET) \$(PHP_MODULES) \$(PHP_ZEND_EX) \$(PHP_BINARIES) $pharcmd"
|
||||
-install_targets="$install_sapi $install_modules $install_binaries install-build install-headers install-programs $install_pear $pharcmd_install"
|
||||
+# PATCH: Don't install includes and build files since php is static.
|
||||
+install_targets="$install_sapi $install_modules $install_binaries install-programs $install_pear $pharcmd_install"
|
||||
|
||||
|
||||
PHP_VAR_SUBST="$PHP_VAR_SUBST all_targets"
|
||||
@@ -98546,6 +98550,7 @@
|
||||
builddir = $abs_builddir
|
||||
top_srcdir = $abs_srcdir
|
||||
top_builddir = $abs_builddir
|
||||
+cross_compiling = $cross_compiling
|
||||
EOF
|
||||
for i in $PHP_VAR_SUBST; do
|
||||
eval echo "$i = \$$i" >> Makefile
|
||||
@@ -98684,11 +98689,7 @@
|
||||
|
||||
|
||||
|
||||
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: patching main/php_config.h.in" >&5
|
||||
-printf "%s\n" "$as_me: patching main/php_config.h.in" >&6;}
|
||||
-
|
||||
- $SED -e 's/^#undef PACKAGE_[^ ]*/\/\* & \*\//g' < $srcdir/main/php_config.h.in \
|
||||
- > $srcdir/main/php_config.h.in.tmp && mv $srcdir/main/php_config.h.in.tmp $srcdir/main/php_config.h.in
|
||||
+# PATCH: Don't rewrite main/php_config.h.in as it is a source file.
|
||||
|
||||
|
||||
: "${CONFIG_STATUS=./config.status}"
|
||||
diff -Paur --no-dereference -- php.upstream/ext/fileinfo/libmagic/file.h php/ext/fileinfo/libmagic/file.h
|
||||
--- php.upstream/ext/fileinfo/libmagic/file.h
|
||||
+++ php/ext/fileinfo/libmagic/file.h
|
||||
@@ -79,9 +79,6 @@
|
||||
#include <fcntl.h> /* For open and flags */
|
||||
|
||||
#include <sys/types.h>
|
||||
-#ifndef WIN32
|
||||
-#include <sys/param.h>
|
||||
-#endif
|
||||
/* Do this here and now, because struct stat gets re-defined on solaris */
|
||||
#include <sys/stat.h>
|
||||
#include <stdarg.h>
|
||||
diff -Paur --no-dereference -- php.upstream/ext/iconv/iconv.c php/ext/iconv/iconv.c
|
||||
--- php.upstream/ext/iconv/iconv.c
|
||||
+++ php/ext/iconv/iconv.c
|
||||
@@ -40,10 +40,6 @@
|
||||
#include <gnu/libc-version.h>
|
||||
#endif
|
||||
|
||||
-#ifdef HAVE_LIBICONV
|
||||
-#undef iconv
|
||||
-#endif
|
||||
-
|
||||
#if defined(__NetBSD__)
|
||||
// unfortunately, netbsd has still the old non posix conformant signature
|
||||
// libiconv tends to match the eventual system's iconv too.
|
||||
diff -Paur --no-dereference -- php.upstream/ext/pdo/Makefile.frag php/ext/pdo/Makefile.frag
|
||||
--- php.upstream/ext/pdo/Makefile.frag
|
||||
+++ php/ext/pdo/Makefile.frag
|
||||
@@ -32,4 +32,4 @@
|
||||
done;
|
||||
|
||||
# mini hack
|
||||
-install: $(all_targets) $(install_targets) install-pdo-headers
|
||||
+install: $(all_targets) $(install_targets)
|
||||
diff -Paur --no-dereference -- php.upstream/ext/phar/Makefile.frag php/ext/phar/Makefile.frag
|
||||
--- php.upstream/ext/phar/Makefile.frag
|
||||
+++ php/ext/phar/Makefile.frag
|
||||
@@ -9,6 +9,11 @@
|
||||
pharcmd: $(builddir)/phar.php $(builddir)/phar.phar
|
||||
|
||||
PHP_PHARCMD_SETTINGS = -n -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' -d phar.readonly=0
|
||||
+
|
||||
+# Cross-compile using a local php that is the same version.
|
||||
+ifeq ($(cross_compiling),yes)
|
||||
+PHP_PHARCMD_EXECUTABLE=php
|
||||
+else
|
||||
PHP_PHARCMD_EXECUTABLE = ` \
|
||||
if test -x "$(top_builddir)/$(SAPI_CLI_PATH)"; then \
|
||||
$(top_srcdir)/build/shtool echo -n -- "$(top_builddir)/$(SAPI_CLI_PATH) -n"; \
|
||||
@@ -23,15 +28,14 @@
|
||||
else \
|
||||
$(top_srcdir)/build/shtool echo -n -- "$(PHP_EXECUTABLE)"; \
|
||||
fi;`
|
||||
-PHP_PHARCMD_BANG = `$(top_srcdir)/build/shtool echo -n -- "$(INSTALL_ROOT)$(bindir)/$(program_prefix)php$(program_suffix)$(EXEEXT)";`
|
||||
+endif
|
||||
+PHP_PHARCMD_BANG = `$(top_srcdir)/build/shtool echo -n -- "$(bindir)/$(program_prefix)php$(program_suffix)$(EXEEXT)";`
|
||||
|
||||
$(builddir)/phar/phar.inc: $(srcdir)/phar/phar.inc
|
||||
-@test -d $(builddir)/phar || mkdir $(builddir)/phar
|
||||
-@test -f $(builddir)/phar/phar.inc || cp $(srcdir)/phar/phar.inc $(builddir)/phar/phar.inc
|
||||
|
||||
-
|
||||
-TEST_PHP_EXECUTABLE = $(shell $(PHP_EXECUTABLE) -v 2>&1)
|
||||
-TEST_PHP_EXECUTABLE_RES = $(shell echo "$(TEST_PHP_EXECUTABLE)" | grep -c 'Exec format error')
|
||||
+TEST_PHP_EXECUTABLE_RES=0
|
||||
|
||||
$(builddir)/phar.php: $(srcdir)/build_precommand.php $(srcdir)/phar/*.inc $(srcdir)/phar/*.php $(SAPI_CLI_PATH)
|
||||
-@(echo "Generating phar.php"; \
|
||||
@@ -60,7 +64,6 @@
|
||||
$(LN_S) -f $(program_prefix)phar$(program_suffix).phar $(INSTALL_ROOT)$(bindir)/$(program_prefix)phar$(program_suffix); \
|
||||
$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1; \
|
||||
$(INSTALL_DATA) $(builddir)/phar.1 $(INSTALL_ROOT)$(mandir)/man1/$(program_prefix)phar$(program_suffix).1; \
|
||||
- $(INSTALL_DATA) $(builddir)/phar.phar.1 $(INSTALL_ROOT)$(mandir)/man1/$(program_prefix)phar$(program_suffix).phar.1; \
|
||||
else \
|
||||
echo "Skipping install-pharcmd during cross compilation"; \
|
||||
fi)
|
||||
diff -Paur --no-dereference -- php.upstream/ext/phar/func_interceptors.c php/ext/phar/func_interceptors.c
|
||||
--- php.upstream/ext/phar/func_interceptors.c
|
||||
+++ php/ext/phar/func_interceptors.c
|
||||
@@ -350,6 +350,7 @@
|
||||
wmask=S_IWGRP;
|
||||
xmask=S_IXGRP;
|
||||
} else {
|
||||
+#if !defined(__sortix__) || defined(__SORTIX_HAS_GETGROUPS__)
|
||||
int groups, n, i;
|
||||
gid_t *gids;
|
||||
|
||||
@@ -367,6 +368,7 @@
|
||||
}
|
||||
efree(gids);
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
|
||||
diff -Paur --no-dereference -- php.upstream/ext/posix/posix.c php/ext/posix/posix.c
|
||||
--- php.upstream/ext/posix/posix.c
|
||||
+++ php/ext/posix/posix.c
|
||||
@@ -266,9 +266,13 @@
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Get current process group id (POSIX.1, 4.3.1) */
|
||||
+static pid_t php_getpgrp(void)
|
||||
+{
|
||||
+ return getpgid(0);
|
||||
+}
|
||||
PHP_FUNCTION(posix_getpgrp)
|
||||
{
|
||||
- PHP_POSIX_RETURN_LONG_FUNC(getpgrp);
|
||||
+ PHP_POSIX_RETURN_LONG_FUNC(php_getpgrp);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/crypt_sha256.c php/ext/standard/crypt_sha256.c
|
||||
--- php.upstream/ext/standard/crypt_sha256.c
|
||||
+++ php/ext/standard/crypt_sha256.c
|
||||
@@ -23,7 +23,6 @@
|
||||
#ifdef PHP_WIN32
|
||||
# include <string.h>
|
||||
#else
|
||||
-# include <sys/param.h>
|
||||
# include <sys/types.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/crypt_sha512.c php/ext/standard/crypt_sha512.c
|
||||
--- php.upstream/ext/standard/crypt_sha512.c
|
||||
+++ php/ext/standard/crypt_sha512.c
|
||||
@@ -22,7 +22,6 @@
|
||||
#ifdef PHP_WIN32
|
||||
# include <string.h>
|
||||
#else
|
||||
-# include <sys/param.h>
|
||||
# include <sys/types.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/dl.c php/ext/standard/dl.c
|
||||
--- php.upstream/ext/standard/dl.c
|
||||
+++ php/ext/standard/dl.c
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "win32/winutil.h"
|
||||
#define GET_DL_ERROR() php_win_err()
|
||||
#else
|
||||
-#include <sys/param.h>
|
||||
#define GET_DL_ERROR() DL_ERROR()
|
||||
#endif
|
||||
#endif /* defined(HAVE_LIBDL) */
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/dns.c php/ext/standard/dns.c
|
||||
--- php.upstream/ext/standard/dns.c
|
||||
+++ php/ext/standard/dns.c
|
||||
@@ -241,9 +241,7 @@
|
||||
{
|
||||
char *hostname;
|
||||
size_t hostname_len;
|
||||
- struct hostent *hp;
|
||||
struct in_addr in;
|
||||
- int i;
|
||||
#ifdef HAVE_INET_NTOP
|
||||
char addr4[INET_ADDRSTRLEN];
|
||||
#endif
|
||||
@@ -258,54 +256,47 @@
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
- hp = php_network_gethostbyname(hostname);
|
||||
- if (!hp) {
|
||||
+ struct addrinfo hints = { .ai_family = AF_INET };
|
||||
+ struct addrinfo *res0 = NULL;
|
||||
+ int status = getaddrinfo(hostname, NULL, &hints, &res0);
|
||||
+ if (status) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
- for (i = 0;; i++) {
|
||||
- /* On macos h_addr_list entries may be misaligned. */
|
||||
- struct in_addr *h_addr_entry; /* Don't call this h_addr, it's a macro! */
|
||||
- memcpy(&h_addr_entry, &hp->h_addr_list[i], sizeof(struct in_addr *));
|
||||
- if (!h_addr_entry) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- in = *h_addr_entry;
|
||||
+ for (struct addrinfo *res = res0; res; res = res->ai_next)
|
||||
+ {
|
||||
+ in = *(struct in_addr *)res->ai_addr;
|
||||
#ifdef HAVE_INET_NTOP
|
||||
add_next_index_string(return_value, inet_ntop(AF_INET, &in, addr4, INET_ADDRSTRLEN));
|
||||
#else
|
||||
add_next_index_string(return_value, inet_ntoa(in));
|
||||
#endif
|
||||
}
|
||||
+ freeaddrinfo(res0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_gethostbyname */
|
||||
static zend_string *php_gethostbyname(char *name)
|
||||
{
|
||||
- struct hostent *hp;
|
||||
- struct in_addr *h_addr_0; /* Don't call this h_addr, it's a macro! */
|
||||
struct in_addr in;
|
||||
#ifdef HAVE_INET_NTOP
|
||||
char addr4[INET_ADDRSTRLEN];
|
||||
#endif
|
||||
const char *address;
|
||||
|
||||
- hp = php_network_gethostbyname(name);
|
||||
- if (!hp) {
|
||||
+ struct addrinfo hints = { .ai_family = AF_INET };
|
||||
+ struct addrinfo *res0 = NULL;
|
||||
+ int status = getaddrinfo(name, NULL, &hints, &res0);
|
||||
+ if (status) {
|
||||
return zend_string_init(name, strlen(name), 0);
|
||||
}
|
||||
|
||||
- /* On macos h_addr_list entries may be misaligned. */
|
||||
- memcpy(&h_addr_0, &hp->h_addr_list[0], sizeof(struct in_addr *));
|
||||
- if (!h_addr_0) {
|
||||
- return zend_string_init(name, strlen(name), 0);
|
||||
- }
|
||||
+ memcpy(&in.s_addr, res0->ai_addr, sizeof(in.s_addr));
|
||||
|
||||
- memcpy(&in.s_addr, h_addr_0, sizeof(in.s_addr));
|
||||
+ freeaddrinfo(res0);
|
||||
|
||||
#ifdef HAVE_INET_NTOP
|
||||
address = inet_ntop(AF_INET, &in, addr4, INET_ADDRSTRLEN);
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/filestat.c php/ext/standard/filestat.c
|
||||
--- php.upstream/ext/standard/filestat.c
|
||||
+++ php/ext/standard/filestat.c
|
||||
@@ -836,6 +836,7 @@
|
||||
wmask=S_IWGRP;
|
||||
xmask=S_IXGRP;
|
||||
} else {
|
||||
+#if !defined(__sortix__) || defined(__SORTIX_HAS_GETGROUPS__)
|
||||
int groups, n, i;
|
||||
gid_t *gids;
|
||||
|
||||
@@ -853,6 +854,7 @@
|
||||
}
|
||||
efree(gids);
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/ftp_fopen_wrapper.c php/ext/standard/ftp_fopen_wrapper.c
|
||||
--- php.upstream/ext/standard/ftp_fopen_wrapper.c
|
||||
+++ php/ext/standard/ftp_fopen_wrapper.c
|
||||
@@ -33,8 +33,6 @@
|
||||
#include <winsock2.h>
|
||||
#define O_RDONLY _O_RDONLY
|
||||
#include "win32/param.h"
|
||||
-#else
|
||||
-#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include "php_standard.h"
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/http_fopen_wrapper.c php/ext/standard/http_fopen_wrapper.c
|
||||
--- php.upstream/ext/standard/http_fopen_wrapper.c
|
||||
+++ php/ext/standard/http_fopen_wrapper.c
|
||||
@@ -36,8 +36,6 @@
|
||||
#ifdef PHP_WIN32
|
||||
#define O_RDONLY _O_RDONLY
|
||||
#include "win32/param.h"
|
||||
-#else
|
||||
-#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include "php_standard.h"
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/microtime.c php/ext/standard/microtime.c
|
||||
--- php.upstream/ext/standard/microtime.c
|
||||
+++ php/ext/standard/microtime.c
|
||||
@@ -125,7 +125,7 @@
|
||||
#ifdef PHP_WIN32 /* Windows only implements a limited amount of fields from the rusage struct */
|
||||
PHP_RUSAGE_PARA(ru_majflt);
|
||||
PHP_RUSAGE_PARA(ru_maxrss);
|
||||
-#elif !defined(_OSD_POSIX) && !defined(__HAIKU__)
|
||||
+#elif !defined(_OSD_POSIX) && !defined(__HAIKU__) && !defined(__sortix__)
|
||||
PHP_RUSAGE_PARA(ru_oublock);
|
||||
PHP_RUSAGE_PARA(ru_inblock);
|
||||
PHP_RUSAGE_PARA(ru_msgsnd);
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/net.c php/ext/standard/net.c
|
||||
--- php.upstream/ext/standard/net.c
|
||||
+++ php/ext/standard/net.c
|
||||
@@ -295,8 +295,14 @@
|
||||
iface_append_unicast(unicast,
|
||||
p->ifa_flags,
|
||||
p->ifa_addr, p->ifa_netmask,
|
||||
- (p->ifa_flags & IFF_BROADCAST) ? p->ifa_broadaddr : NULL,
|
||||
- (p->ifa_flags & IFF_POINTOPOINT) ? p->ifa_dstaddr : NULL);
|
||||
+#ifdef IFF_BROADCAST
|
||||
+ (p->ifa_flags & IFF_BROADCAST) ? p->ifa_broadaddr :
|
||||
+#endif
|
||||
+ NULL,
|
||||
+#ifdef IFF_POINTOPOINT
|
||||
+ (p->ifa_flags & IFF_POINTOPOINT) ? p->ifa_dstaddr :
|
||||
+#endif
|
||||
+ NULL);
|
||||
status = zend_hash_str_find(Z_ARR_P(iface), "up", sizeof("up") - 1);
|
||||
if (!status) {
|
||||
add_assoc_bool(iface, "up", ((p->ifa_flags & IFF_UP) != 0));
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/pack.c php/ext/standard/pack.c
|
||||
--- php.upstream/ext/standard/pack.c
|
||||
+++ php/ext/standard/pack.c
|
||||
@@ -25,8 +25,6 @@
|
||||
#ifdef PHP_WIN32
|
||||
#define O_RDONLY _O_RDONLY
|
||||
#include "win32/param.h"
|
||||
-#else
|
||||
-#include <sys/param.h>
|
||||
#endif
|
||||
#include "ext/standard/head.h"
|
||||
#include "php_string.h"
|
||||
diff -Paur --no-dereference -- php.upstream/ext/standard/php_fopen_wrapper.c php/ext/standard/php_fopen_wrapper.c
|
||||
--- php.upstream/ext/standard/php_fopen_wrapper.c
|
||||
+++ php/ext/standard/php_fopen_wrapper.c
|
||||
@@ -317,11 +317,7 @@
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-#ifdef HAVE_UNISTD_H
|
||||
- dtablesize = getdtablesize();
|
||||
-#else
|
||||
dtablesize = INT_MAX;
|
||||
-#endif
|
||||
|
||||
if (fildes_ori < 0 || fildes_ori >= dtablesize) {
|
||||
php_stream_wrapper_log_error(wrapper, options,
|
||||
diff -Paur --no-dereference -- php.upstream/init/php-fpm php/init/php-fpm
|
||||
--- php.upstream/init/php-fpm
|
||||
+++ php/init/php-fpm
|
||||
@@ -0,0 +1 @@
|
||||
+exec php-fpm -FO
|
||||
diff -Paur --no-dereference -- php.upstream/main/fastcgi.c php/main/fastcgi.c
|
||||
--- php.upstream/main/fastcgi.c
|
||||
+++ php/main/fastcgi.c
|
||||
@@ -689,21 +689,17 @@
|
||||
sa.sa_inet.sin_addr.s_addr = inet_addr(host);
|
||||
if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) {
|
||||
#endif
|
||||
- struct hostent *hep;
|
||||
-
|
||||
- if(strlen(host) > MAXFQDNLEN) {
|
||||
- hep = NULL;
|
||||
- } else {
|
||||
- hep = php_network_gethostbyname(host);
|
||||
- }
|
||||
- if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) {
|
||||
+ struct addrinfo hints = { .ai_family = AF_INET };
|
||||
+ struct addrinfo *res0 = NULL;
|
||||
+ int status = getaddrinfo(host, NULL, &hints, &res0);
|
||||
+ if (status) {
|
||||
fcgi_log(FCGI_ERROR, "Cannot resolve host name '%s'!\n", host);
|
||||
- return -1;
|
||||
- } else if (hep->h_addr_list[1]) {
|
||||
+ } else if (res0->ai_next) {
|
||||
fcgi_log(FCGI_ERROR, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host);
|
||||
return -1;
|
||||
}
|
||||
- sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr;
|
||||
+ sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)res0->ai_addr)->s_addr;
|
||||
+ freeaddrinfo(res0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
diff -Paur --no-dereference -- php.upstream/main/fopen_wrappers.c php/main/fopen_wrappers.c
|
||||
--- php.upstream/main/fopen_wrappers.c
|
||||
+++ php/main/fopen_wrappers.c
|
||||
@@ -30,8 +30,6 @@
|
||||
#ifdef PHP_WIN32
|
||||
#define O_RDONLY _O_RDONLY
|
||||
#include "win32/param.h"
|
||||
-#else
|
||||
-#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include "ext/standard/head.h"
|
||||
diff -Paur --no-dereference -- php.upstream/main/network.c php/main/network.c
|
||||
--- php.upstream/main/network.c
|
||||
+++ php/main/network.c
|
||||
@@ -29,8 +29,6 @@
|
||||
# include "win32/winutil.h"
|
||||
# define O_RDONLY _O_RDONLY
|
||||
# include "win32/param.h"
|
||||
-#else
|
||||
-#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -74,6 +72,11 @@
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
+#if defined(__sortix__) && !defined(timercmp)
|
||||
+#define timercmp(s,t,op) ((s)->tv_sec == (t)->tv_sec ? \
|
||||
+ (s)->tv_usec op (t)->tv_usec : (s)->tv_sec op (t)->tv_sec)
|
||||
+#endif
|
||||
+
|
||||
#include "ext/standard/file.h"
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
@@ -247,6 +250,8 @@
|
||||
errno = E2BIG;
|
||||
} else {
|
||||
host_info = php_network_gethostbyname(host);
|
||||
+ host_info = NULL;
|
||||
+ errno = ENOTSUP;
|
||||
}
|
||||
if (host_info == NULL) {
|
||||
if (error_string) {
|
||||
@@ -871,9 +876,9 @@
|
||||
if (inet_aton(bindto, &local_address.in4.sin_addr)) {
|
||||
#endif
|
||||
local_address_len = sizeof(struct sockaddr_in);
|
||||
+ memset(&(local_address.in4), 0, sizeof(local_address.in4));
|
||||
local_address.in4.sin_family = sa->sa_family;
|
||||
local_address.in4.sin_port = htons(bindport);
|
||||
- memset(&(local_address.in4.sin_zero), 0, sizeof(local_address.in4.sin_zero));
|
||||
}
|
||||
}
|
||||
#if HAVE_IPV6 && HAVE_INET_PTON
|
||||
@@ -1330,7 +1335,7 @@
|
||||
|
||||
PHPAPI struct hostent* php_network_gethostbyname(const char *name) {
|
||||
#if !defined(HAVE_GETHOSTBYNAME_R)
|
||||
- return gethostbyname(name);
|
||||
+ return NULL; // PATCH: Only use getaddrinfo.
|
||||
#else
|
||||
if (FG(tmp_host_buf)) {
|
||||
free(FG(tmp_host_buf));
|
||||
diff -Paur --no-dereference -- php.upstream/main/php.h php/main/php.h
|
||||
--- php.upstream/main/php.h
|
||||
+++ php/main/php.h
|
||||
@@ -225,7 +225,6 @@
|
||||
#include "win32/param.h"
|
||||
# else
|
||||
#include <pwd.h>
|
||||
-#include <sys/param.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
diff -Paur --no-dereference -- php.upstream/main/php_open_temporary_file.c php/main/php_open_temporary_file.c
|
||||
--- php.upstream/main/php_open_temporary_file.c
|
||||
+++ php/main/php_open_temporary_file.c
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "win32/param.h"
|
||||
#include "win32/winutil.h"
|
||||
#else
|
||||
-#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
@@ -43,10 +42,6 @@
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
-#if !defined(P_tmpdir)
|
||||
-#define P_tmpdir ""
|
||||
-#endif
|
||||
-
|
||||
/* {{{ php_do_open_temporary_file */
|
||||
|
||||
/* Loosely based on a tempnam() implementation by UCLA */
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/cgi/cgi_main.c php/sapi/cgi/cgi_main.c
|
||||
--- php.upstream/sapi/cgi/cgi_main.c
|
||||
+++ php/sapi/cgi/cgi_main.c
|
||||
@@ -1989,7 +1989,7 @@
|
||||
|
||||
/* Create a process group for us & children */
|
||||
setsid();
|
||||
- pgroup = getpgrp();
|
||||
+ pgroup = getpgid(0);
|
||||
#ifdef DEBUG_FASTCGI
|
||||
fprintf(stderr, "Process group %d\n", pgroup);
|
||||
#endif
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/Makefile.frag php/sapi/fpm/Makefile.frag
|
||||
--- php.upstream/sapi/fpm/Makefile.frag
|
||||
+++ php/sapi/fpm/Makefile.frag
|
||||
@@ -14,10 +14,18 @@
|
||||
echo "Installing PHP FPM defconfig: skipping"; \
|
||||
else \
|
||||
echo "Installing PHP FPM defconfig: $(INSTALL_ROOT)$(sysconfdir)/" && \
|
||||
- $(mkinstalldirs) $(INSTALL_ROOT)$(sysconfdir)/php-fpm.d; \
|
||||
- $(INSTALL_DATA) sapi/fpm/php-fpm.conf $(INSTALL_ROOT)$(sysconfdir)/php-fpm.conf.default; \
|
||||
- $(INSTALL_DATA) sapi/fpm/www.conf $(INSTALL_ROOT)$(sysconfdir)/php-fpm.d/www.conf.default; \
|
||||
+ $(mkinstalldirs) $(INSTALL_ROOT)$(sysconfdir)/default/php-fpm.d; \
|
||||
+ $(INSTALL_DATA) sapi/fpm/php-fpm.conf $(INSTALL_ROOT)$(sysconfdir)/default/php-fpm.conf; \
|
||||
+ $(INSTALL_DATA) sapi/fpm/www.conf $(INSTALL_ROOT)$(sysconfdir)/default/php-fpm.d/www.conf; \
|
||||
fi
|
||||
+ mkdir -p $(INSTALL_ROOT)$(datarootdir)/init
|
||||
+ cp init/php-fpm $(INSTALL_ROOT)$(datarootdir)/init/php-fpm
|
||||
+ mkdir -p '$(INSTALL_ROOT)$(sysconfdir)/default/passwd.d'
|
||||
+ mkdir -p '$(INSTALL_ROOT)$(sysconfdir)/default/group.d'
|
||||
+ echo "_php-fpm:x:102:102:_php-fpm:/var/empty:sh" \
|
||||
+ > '$(INSTALL_ROOT)$(sysconfdir)/default/passwd.d/php'
|
||||
+ echo "_php-fpm::102:_php-fpm,_nginx" \
|
||||
+ > '$(INSTALL_ROOT)$(sysconfdir)/default/group.d/php'
|
||||
|
||||
@echo "Installing PHP FPM man page: $(INSTALL_ROOT)$(mandir)/man8/"
|
||||
@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man8
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/fpm/fpm_children.c php/sapi/fpm/fpm/fpm_children.c
|
||||
--- php.upstream/sapi/fpm/fpm/fpm_children.c
|
||||
+++ php/sapi/fpm/fpm/fpm_children.c
|
||||
@@ -272,7 +272,7 @@
|
||||
}
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
|
||||
- zlog(ZLOG_NOTICE, "child %d stopped for tracing", (int) pid);
|
||||
+ zlog(ZLOG_NOTICE, "child %jd stopped for tracing", (intmax_t) pid);
|
||||
|
||||
if (child && child->tracer) {
|
||||
child->tracer(child);
|
||||
@@ -297,9 +297,9 @@
|
||||
if (!fpm_pctl_can_spawn_children()) {
|
||||
severity = ZLOG_DEBUG;
|
||||
}
|
||||
- zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", wp->config->name, (int) pid, buf, (long)tv2.tv_sec, (int) tv2.tv_usec);
|
||||
+ zlog(severity, "[pool %s] child %jd exited %s after %ld.%06d seconds from start", wp->config->name, (intmax_t) pid, buf, (long)tv2.tv_sec, (int) tv2.tv_usec);
|
||||
} else {
|
||||
- zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process management after %ld.%06d seconds from start", wp->config->name, (int) pid, (long)tv2.tv_sec, (int) tv2.tv_usec);
|
||||
+ zlog(ZLOG_DEBUG, "[pool %s] child %jd has been killed by the process management after %ld.%06d seconds from start", wp->config->name, (intmax_t) pid, (long)tv2.tv_sec, (int) tv2.tv_usec);
|
||||
}
|
||||
|
||||
fpm_child_close(child, 1 /* in event_loop */);
|
||||
@@ -340,9 +340,9 @@
|
||||
}
|
||||
}
|
||||
} else if (fpm_globals.parent_pid == 1) {
|
||||
- zlog(ZLOG_DEBUG, "unknown child (%d) exited %s - most likely an orphan process (master process is the init process)", pid, buf);
|
||||
+ zlog(ZLOG_DEBUG, "unknown child (%jd) exited %s - most likely an orphan process (master process is the init process)", (intmax_t) pid, buf);
|
||||
} else {
|
||||
- zlog(ZLOG_WARNING, "unknown child (%d) exited %s - potentially a bug or pre exec child (e.g. s6-notifyoncheck)", pid, buf);
|
||||
+ zlog(ZLOG_WARNING, "unknown child (%jd) exited %s - potentially a bug or pre exec child (e.g. s6-notifyoncheck)", (intmax_t) pid, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/fpm/fpm_conf.c php/sapi/fpm/fpm/fpm_conf.c
|
||||
--- php.upstream/sapi/fpm/fpm/fpm_conf.c
|
||||
+++ php/sapi/fpm/fpm/fpm_conf.c
|
||||
@@ -1846,6 +1846,20 @@
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ /* PATCH: Search /etc/default for packaged default config. */
|
||||
+ if (access(tmp, F_OK) < 0 && errno == ENOENT) {
|
||||
+ efree(tmp);
|
||||
+ if (fpm_globals.prefix == NULL) {
|
||||
+ spprintf(&tmp, 0, "%s/default/php-fpm.conf", PHP_SYSCONFDIR);
|
||||
+ } else {
|
||||
+ spprintf(&tmp, 0, "%s/etc/default/php-fpm.conf", fpm_globals.prefix);
|
||||
+ }
|
||||
+ if (!tmp) {
|
||||
+ zlog(ZLOG_SYSERROR, "spprintf() failed (tmp for fpm_globals.config)");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
fpm_globals.config = strdup(tmp);
|
||||
efree(tmp);
|
||||
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/fpm/fpm_main.c php/sapi/fpm/fpm/fpm_main.c
|
||||
--- php.upstream/sapi/fpm/fpm/fpm_main.c
|
||||
+++ php/sapi/fpm/fpm/fpm_main.c
|
||||
@@ -1844,6 +1844,14 @@
|
||||
}
|
||||
fpm_is_running = 1;
|
||||
|
||||
+ if (getenv("READYFD")) {
|
||||
+ int readyfd = atoi(getenv("READYFD"));
|
||||
+ char c = '\n';
|
||||
+ write(readyfd, &c, 1);
|
||||
+ close(readyfd);
|
||||
+ unsetenv("READYFD");
|
||||
+ }
|
||||
+
|
||||
fcgi_fd = fpm_run(&max_requests);
|
||||
parent = 0;
|
||||
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/fpm/fpm_shm.c php/sapi/fpm/fpm/fpm_shm.c
|
||||
--- php.upstream/sapi/fpm/fpm/fpm_shm.c
|
||||
+++ php/sapi/fpm/fpm/fpm_shm.c
|
||||
@@ -19,7 +19,11 @@
|
||||
{
|
||||
void *mem;
|
||||
|
||||
+#if defined(__sortix__) && !defined(__SORTIX_HAS_WORKING_MAP_SHARED__)
|
||||
+ mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
+#else
|
||||
mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||
+#endif
|
||||
|
||||
#ifdef MAP_FAILED
|
||||
if (mem == MAP_FAILED) {
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/fpm/fpm_trace_pread.c php/sapi/fpm/fpm/fpm_trace_pread.c
|
||||
--- php.upstream/sapi/fpm/fpm/fpm_trace_pread.c
|
||||
+++ php/sapi/fpm/fpm/fpm_trace_pread.c
|
||||
@@ -22,7 +22,7 @@
|
||||
int fpm_trace_signal(pid_t pid) /* {{{ */
|
||||
{
|
||||
if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
|
||||
- zlog(ZLOG_SYSERROR, "failed to send SIGSTOP to %d", pid);
|
||||
+ zlog(ZLOG_SYSERROR, "failed to send SIGSTOP to %jd", (intmax_t)pid);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/fpm/fpm_unix.c php/sapi/fpm/fpm/fpm_unix.c
|
||||
--- php.upstream/sapi/fpm/fpm/fpm_unix.c
|
||||
+++ php/sapi/fpm/fpm/fpm_unix.c
|
||||
@@ -481,10 +481,12 @@
|
||||
}
|
||||
}
|
||||
if (wp->set_uid) {
|
||||
+#if !defined(__sortix__) || defined(__SORTIX_HAS_INITGROUPS__)
|
||||
if (0 > initgroups(wp->set_user ? wp->set_user : wp->config->user, wp->set_gid)) {
|
||||
zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid);
|
||||
return -1;
|
||||
}
|
||||
+#endif
|
||||
if (0 > setuid(wp->set_uid)) {
|
||||
zlog(ZLOG_SYSERROR, "[pool %s] failed to setuid(%d)", wp->config->name, wp->set_uid);
|
||||
return -1;
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/fpm/zlog.c php/sapi/fpm/fpm/zlog.c
|
||||
--- php.upstream/sapi/fpm/fpm/zlog.c
|
||||
+++ php/sapi/fpm/fpm/zlog.c
|
||||
@@ -177,8 +177,8 @@
|
||||
}
|
||||
if (zlog_level == ZLOG_DEBUG) {
|
||||
if (!fpm_globals.is_child) {
|
||||
- len += snprintf(buf + len, buf_size - len, "%s: pid %d, %s(), line %d: ",
|
||||
- level_names[flags & ZLOG_LEVEL_MASK], getpid(), function, line);
|
||||
+ len += snprintf(buf + len, buf_size - len, "%s: pid %jd, %s(), line %d: ",
|
||||
+ level_names[flags & ZLOG_LEVEL_MASK], (intmax_t)getpid(), function, line);
|
||||
} else {
|
||||
len += snprintf(buf + len, buf_size - len, "%s: %s(), line %d: ",
|
||||
level_names[flags & ZLOG_LEVEL_MASK], function, line);
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/php-fpm.conf.in php/sapi/fpm/php-fpm.conf.in
|
||||
--- php.upstream/sapi/fpm/php-fpm.conf.in
|
||||
+++ php/sapi/fpm/php-fpm.conf.in
|
||||
@@ -140,4 +140,4 @@
|
||||
; Relative path can also be used. They will be prefixed by:
|
||||
; - the global prefix if it's been set (-p argument)
|
||||
; - @prefix@ otherwise
|
||||
-include=@php_fpm_sysconfdir@/php-fpm.d/*.conf
|
||||
+include=@php_fpm_sysconfdir@/default/php-fpm.d/*.conf
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/fpm/www.conf.in php/sapi/fpm/www.conf.in
|
||||
--- php.upstream/sapi/fpm/www.conf.in
|
||||
+++ php/sapi/fpm/www.conf.in
|
||||
@@ -38,7 +38,8 @@
|
||||
; (IPv6 and IPv4-mapped) on a specific port;
|
||||
; '/path/to/unix/socket' - to listen on a unix socket.
|
||||
; Note: This value is mandatory.
|
||||
-listen = 127.0.0.1:9000
|
||||
+; listen = 127.0.0.1:9000 ; php upstream default
|
||||
+listen = /var/run/php-fpm
|
||||
|
||||
; Set listen(2) backlog.
|
||||
; Default Value: 511 (-1 on Linux, FreeBSD and OpenBSD)
|
||||
diff -Paur --no-dereference -- php.upstream/sapi/phpdbg/phpdbg_prompt.c php/sapi/phpdbg/phpdbg_prompt.c
|
||||
--- php.upstream/sapi/phpdbg/phpdbg_prompt.c
|
||||
+++ php/sapi/phpdbg/phpdbg_prompt.c
|
||||
@@ -54,7 +54,6 @@
|
||||
#include "win32/winutil.h"
|
||||
#define GET_DL_ERROR() php_win_err()
|
||||
#else
|
||||
-#include <sys/param.h>
|
||||
#define GET_DL_ERROR() DL_ERROR()
|
||||
#endif
|
||||
#endif
|
||||
diff -Paur --no-dereference -- php.upstream/scripts/Makefile.frag php/scripts/Makefile.frag
|
||||
--- php.upstream/scripts/Makefile.frag
|
||||
+++ php/scripts/Makefile.frag
|
||||
@@ -23,8 +23,10 @@
|
||||
build/config.guess \
|
||||
build/config.sub
|
||||
|
||||
-bin_SCRIPTS = phpize php-config
|
||||
-man_PAGES = phpize php-config
|
||||
+# PATCH: pkg-config must be used instead of foo-config.
|
||||
+# PATCH: phpize is not useful when statically linked.
|
||||
+bin_SCRIPTS =
|
||||
+man_PAGES =
|
||||
|
||||
install-build:
|
||||
@echo "Installing build environment: $(INSTALL_ROOT)$(phpbuilddir)/"
|
||||
@@ -33,7 +35,7 @@
|
||||
$(INSTALL) $(BUILD_FILES_EXEC) $(INSTALL_ROOT)$(phpbuilddir) && \
|
||||
$(INSTALL_DATA) $(BUILD_FILES) $(INSTALL_ROOT)$(phpbuilddir))
|
||||
|
||||
-install-programs: $(builddir)/phpize $(builddir)/php-config
|
||||
+install-programs:
|
||||
@echo "Installing helper programs: $(INSTALL_ROOT)$(bindir)/"
|
||||
@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
|
||||
@for prog in $(bin_SCRIPTS); do \
|
|
@ -0,0 +1,18 @@
|
|||
NAME=php
|
||||
BUILD_LIBRARIES='libiconv libsqlite3 libxml2 libbz2? libcurl? libffi? libintl? libgmp? libreadline? liblzma? libssl? libpcre? libz?'
|
||||
VERSION=8.3.6
|
||||
DISTNAME=$NAME-$VERSION
|
||||
COMPRESSION=tar.gz
|
||||
ARCHIVE=$DISTNAME.$COMPRESSION
|
||||
SHA256SUM=39695f5bd107892e36fd2ed6b3d3a78140fd4b05d556d6c6531a921633cacb5f
|
||||
UPSTREAM_SITE=https://www.php.net/distributions
|
||||
UPSTREAM_ARCHIVE=$ARCHIVE
|
||||
RELEASE_SEARCH_PAGE=https://www.php.net/downloads.php
|
||||
LICENSE=LICENSE=PHP-3.0
|
||||
USE_BOOTSTRAP=true # php uses php to build phar
|
||||
BOOTSTRAP_BUILD_SYSTEM=configure
|
||||
BOOTSTRAP_CONFIGURE_ARGS='--with-layout=GNU --disable-cgi --disable-phpdbg --disable-all --enable-phar'
|
||||
BOOTSTRAP_MAKE_VARS='V=1'
|
||||
BUILD_SYSTEM=configure
|
||||
CONFIGURE_ARGS='--with-layout=GNU --disable-opcache --disable-fileinfo --enable-mbstring --disable-mbregex --enable-fpm --with-fpm-user=_php-fpm --with-fpm-group=_php-fpm'
|
||||
MAKE_VARS='V=1'
|
Loading…
Reference in New Issue